-
Notifications
You must be signed in to change notification settings - Fork 7.4k
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
Support a language server (like ccls or clangd) (IDFGH-4929) #6721
Comments
@roberti42 I'm afraid you will need to get some suggestions from ccls documentation or issue tracker on debugging this issue. When running My guess is that ccls tries to pass the arguments found in compile_commands.json to clang, which fails because 1) some of the options are architecture-specific (e.g. |
Thank you @igrr, I understand that this is related to ccls (or clangd) more than esp-idf. Is there any alternative to use features such as code completion and the like when developing using esp-idf? |
Just wanted to say this is the only thing I am missing from esp-idf. I have tried clangd and ccls without getting a configuration that works. I am stuck with an error I can't get passed (for anyone else like me who stumbles here):
So far the
|
I seem to have it working with neovim-0.5, the built in LSP, and clangd 12. I added this lua code to the configuration in init.vim
I was able to remove all of the -I lines from the .clangd file. It seems clangd still wants to pick up stuff like <stdio.h> from the system include dirs instead of those that the xtensa toolchain uses. Everything else is working though, I can quickly navigate through all the FreeRTOS and ESP-IDF source like I wanted. |
@mikebwilliams, could you clarify how you've configured Nvim?
I get "Client 1 quit with exit code 1 and signal 0" message in a status bar and LSP is not working at all. |
Did you set the --query-driver to the location of the toolchain on your computer? It's set to /home/mike/... in the command above |
Yes, my compiler path is /Users/dsalnikov/.espressif/tools/xtensa-esp32-elf/esp-2021r1-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc, so as a cmd I use "/Users/dsalnikov/.espressif/tools/xtensa-esp32-elf/esp-2021r1-8.4.0/**/bin/xtensa-esp32-elf-*" Looks like I have to specify commands separately:
Now LSP starts fine. PS |
Has anyone gotten rid of this error?
I get it when including certain esp-idf headers, such as <esp_wifi.h>. Simple example to demonstrate:
The lsp logs show that it's compiling a native target-triple: Perhaps there's a more compatible target-triple we can use? |
So what's happening is clangd doesn't recognize Getting everything working required cloning the xtensa llvm fork at https://github.com/espressif/llvm-project and building clangd from there:
Then simply use the clangd in This is my
To easily make it work for everyone Espressif simply needs to build and distribute clangd in their existing xtensa-clang (that can be downloaded with |
Thanks for the recommendation @tolgraven, I'll create a task to add clangd to the next xtensa-clang update. |
Thanks for this, it works! I'm sure it would be much appreciated to have clangd included in xtensa-clang, as compile time is pretty long. |
It really makes such a difference having a proper LSP and not just tags and vim-fu. Really wish I'd gotten around to figuring this out sooner - solution far too obvious in retrospect. Is it just me or is [presumably this version of] clangd/clang rather buggy? I'm getting inexplicable errors like Renderer::Renderer(const std::string& id, uint16_t keyFrameHz, uint16_t targetHz, const RenderStage& target):
RenderStage(id + " renderer", target.fieldSize(),
target.fieldCount(), target.buffers().size()),
core::Task(id.c_str(), 4096, taskPrio,
milliseconds{1000/targetHz},
0),
Sub<PatchIn>(this),
// ^ clang expected_either - Expected '(' or '{' // which is utter nonsense and since it's not
targetFps(targetHz) { // an actual error there's no way to make it go away...
... Bunch of stuff like that (plus obviously the many quirks in gcc/clang in what will cause a warning or error, or simply silently compile. Anyone got a clue what might be going on? |
@tolgraven and @danngreen can you please share how you build clangd? I followed @tolgraven's suggestion and cloned the llvm-project repo and ran the cmake commands mentioned in that comment. But I'm getting Thank you. |
@listout:
Maybe check which branch you're building? I notice the default branch is not It built for me on macOS 12 (intel hardware), with 16GB of memory, I'd be surprised if that's not enough. @tolgraven |
@danngreen thank you. I'll try again. |
Just to be clear, I was able to build commit 7b5afb55f5c7959a2903978a25774c75172e8741 |
I was finally able to build it with the additional argument @danngreen Nope the same issues, don't know whats happening but the linker is failing on me. Maybe I'll need to dig into it deeper. My exact error message was: |
Thanks for this idea, did it on two different macs and now I've got lsp + emacs running great! The alternative I used before that was ccls but the lsp flychecker disabled. The flycheck config was in .dir-local and used xtensa's g++ with command line copied from the generated .ccls file. Worked OK, but clangd is much better. |
Edit: Okay, I manually downloaded the latest release asset and clangd is included, so. How does one download the latest releases with idf_tools.py, it this releated to not using the master branch as I'm on stable branch (v4.4). |
@listout could you please post the URL of the update you are referring to? I'll check. |
@igrr I was referring to this repo https://github.com/espressif/llvm-project.git. The latest release seems to be 12 days ago. My bad, I meant new release. Looking at the download logs, it's most probably not pulling latest github release assets as it downloads Edit: Okay, I manually downloaded the latest release asset and clangd is indeed included. So, how does one download the latest releases with idf_tools.py? Is it releated to not using the master branch as I'm on stable branch (v4.4). |
@listout I think we haven't updated the download link in tools.json, so the old version is still downloaded when you run idf_tools.py. We will update the link soon. In the meantime you can simply avoid running |
@igrr Thanks. Did just that. |
Has anyone else tried running the latest esp clangd under Mac OS13 Ventura? I get a security warning when I run binary either directly or via neovim. Does anyone have a workaround? Thanks in advance. |
@andychess I've checked on one computer running macOS 13, but couldn't reproduce this issue. What does the warning say, exactly? If that is the case, please check if you have quarantine attribute set on the clangd:
if that prints a line which looks like At that point you can remove the quarantine attribute using If instead you see |
@igrr Thank you Ivan for answering so quickly. The warning is indeed the one that you refer to (clangd" can't be opened because Apple cannot check it for malicious software). I ran $ xattr... as you suggested above and received the reply: xattr: /usr/bin/clangd: No such xattr: com.apple.quarantine I have read elsewhere that MacOS 13 implements a new version of Gatekeeper that is more difficult to circumvent. Interesting that you did not encounter the problem. In my case, I downloaded the latest file from (llvm-esp-15.0.0-20221201-macos.tar.xz) to my Download directory, expanded the file and moved the esp-clang folder to my home directory. Running clangd from the command line and from the cmd: line in neovim both produce the warning. It looks like I may have found the answer here: https://support.apple.com/de-de/guide/mac-help/mchleab3a043/mac (in German). The new way to run quarantined apps is to navigate to the required directory in Finder and hold CTRL and left click on the app. The select 'Open' from the menu. This produces a prompt that will allow the app to run. I had to repeat this step for several files in the folder and then clangd ran for me. I hope this is useful to anyone who experiences the same issue and thanks again Ivan for pointing me in the right direction! |
This means that you are checking the OS-provided copy of clangd (in /usr/bin), not the ESP-specific one. When I wrote the command |
Yes, I only noticed that after I had posted my response. Nevertheless, your answer pointed me in the right direction and everything is working fine now. I'm really pleased with the result. Thank you :-). |
I was able to get clangd working without errors:
|
@xjzi See also clangd/clangd#537 (comment)
|
@joaotavora please note that these arguments aren't the same thing. -mlongcalls is an argument of Xtensa compiler, while -mlong-calls is an argument of an x86 compiler. I am not sure the recommendation to use clang targeting x86-64 instead of Xtensa is helpful. If you do so, various macro expansions which depend on architecture (such as |
Right. Your pasting from the other post and a part which i myself noted was the wrong fix. Later on, if you read the full post, or just read above, you'll notice I just removed it from static analysis. As far as I can understand it only affects code generation and thus is useless for Clangd ally. So even the wrong
As far as I was able to tell from my experience, which so far has been positive --and admittedly limited -- Clangd actually calls the compiler with something like Anyway, that's what's its
Building with xtensa GCC is fine, and so would building with xtensa Clang probably. But in this case i just need clangd, the language server, to understand the code and give me intellisense, etc. Contrary to most other tools for this architecture (compiler, debugger, linker, disassembler) there shouldn't be a need for a special build of the code analysis toolkit. |
@joaotavora Interesting, thanks for sharing this! Have you noticed any issues with resolution of types, e.g. due to different definitions of built-in types between the host and target architectures? For example, do you get correct resolution of something like This is something we ran into with clang-tidy; even with all correct the system headers provided, the differences in evaluation of built-in types prevented clang-tidy from correctly analyzing Xtensa code. On the other hand, clang-tidy built from a version of Clang with Xtensa support had no issue with that. |
@igrr So far no problem -- though I've only been dabling around in relatively small ESP-IDF projects. But so far so good, completion and analysis match exactly (though with different compiler messages), what the To get around the types defined with
Yes, I know For reference here's a fragment of my
EDIT: Sorry I forgot to remind you that
The clangd language server I have installed is the stock version available for Archlinux. version 16 is already available but I haven't yet felt the need to upgrade.
I see the main advantage in this approach that apparently you can use the latest and greatest |
I also battled this week with the language server and here are my tips ...
.clangd conf:
Still using these settings I get some errors when in the header file I think it is also beneficial to the community to make a documentation about the language server use. Using a mac myself I found that using the clangd compiled with xtensa makes for a much better developer experience. Clion (using clangd as backend) out of the box also does not manage very well espressif projects so the language server setting here is very important. |
Same problem, but I solved that by specifying gcc instead of g++ to the query-driver option. Next person who reads this working on a mixed C and C++ project should test providing both options to see if it works. Ironically enough, when compiling my project with clang, clangd can't find some system headers, like |
Hi, I just got started with the ESP32 today and followed a quick tutorial by Low Level Learning to get started with esp-idf. I'm using Neovim with the clangd LSP as my dev environment, but I'm getting a few errors in my source file even though the project compiles normally. I think my issue is related, so I'm going to comment here rather than opening a new issue.
My source file is just the default, but also has some errors from the LSP:
Can someone help me out? Apologies if there is already a solution here that I just didn't see... this thread is quite long 😅 |
I'm running Neovim / Espidf as well. Have you got a .clangd file in your root directory? Mine looks like this: CompileFlags: The last one is necessary for the RISCV chips. |
@andychess This is great, thanks! Have you also encountered errors with including FreeRTOS before? I'm getting |
@j0of Glad it helped :-). Problems with the headers seem to be very common with clang. You probably need a section like this in the lsp config section of nvim. Mine looks like this at the moment. 1 require("mason").setup() 31 require('lspconfig').clangd.setup { I've had to use a lot of trial and error with this as nvim seems to be very sensitive to syntax issues. In theory, it should be possible to use wildcards, but for some reason I often have to put in the full path. Perhaps someone can supply a bit more background to this? The link you supplied was very interesting btw. I didn't know about the line in export.sh. |
After a few more changes to the config, I finally got it to work, and it only took 2 days! 😂 Thanks again for the helpful replies @andychess . I'm gonna leave my solution here, partially to help any others who need help, but mainly to save future me from a massive headache if I somehow find myself in the same situation in the future. Prerequisites
.clangd config
Neovim Lspconfig
|
@j0of Thanks for the config, i improved upon it to allow using a default config whenever we're not in an esp-idf enviroment:
|
@SotchNam @j0of Thank you for the example configs guys, I finally got my setup working 😃 Has anyone else ran into the problem where clangd is using the wrong stdint types (even though it finds all the right headers)? I checked the output from each compiler on my system, and sure enough clang doesn't agree about these defines. Only the 32-bit int types seem to disagree: ~/.espressif/tools
✦ ❯ ./xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/xtensa-esp-elf-g++ -dM -xc++ /dev/null -c -v -E 2> /dev/null | rg "U?INT\d+_TYPE" | sort
#define __INT16_TYPE__ short int
#define __INT32_TYPE__ long int
#define __INT64_TYPE__ long long int
#define __INT8_TYPE__ signed char
#define __UINT16_TYPE__ short unsigned int
#define __UINT32_TYPE__ long unsigned int
#define __UINT64_TYPE__ long long unsigned int
#define __UINT8_TYPE__ unsigned char
~/.espressif/tools
✦ ❯ ./esp-clang/16.0.1-fe4f10a809/esp-clang/bin/clang++ --target=xtensa-esp32s3-elf -dM -xc++ /dev/null -c -v -E 2> /dev/null | rg "U?INT\d+_TYPE" | sort
#define __INT16_TYPE__ short
#define __INT32_TYPE__ int
#define __INT64_TYPE__ long long int
#define __INT8_TYPE__ signed char
#define __UINT16_TYPE__ unsigned short
#define __UINT32_TYPE__ unsigned int
#define __UINT64_TYPE__ long long unsigned int
#define __UINT8_TYPE__ unsigned char
I was able to override the 32-bit defines in my .clangd and now have no warnings (at least for now, there are probably other inconsistencies in less frequent types). Oh, and I figured out a way to let you use a wildcard to find clangd (assuming you have only one installed). This way you don't need to modify your config whenever you update clangd: if esp_idf_path then
local clangd = vim.fn.expand('/home/me/.espressif/tools/esp-clang/*/esp-clang/bin/clangd')
lspconfig.clangd.setup{
-- handlers = handlers,
capabilities = capabilities;
cmd = { clangd, '--background-index', '--query-driver=**', },
... And my .clangd for reference: CompileFlags:
CompilationDatabase: build
QueryDriver: /home/me/.espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc
Add:
- --target=xtensa-esp32s3-elf
- -D__INT32_TYPE__=long int
- -D__UINT32_TYPE__=long unsigned int
Remove:
- -fno-tree-switch-conversion
- -fno-shrink-wrap
- -mtext-section-literals
- -mlongcalls
- -fstrict-volatile-bitfields
- -mdisable-hardware-atomics
- -march=rv32imac_zicsr_zifencei
It appears to handle the quoting properly for the defines (not sure if it will also work for the array-like syntax). I don't think the target argument helps, but it doesn't hurt (as far as I know). I also redundantly specify the query driver in .clangd, since there it makes sense to hard-code it to your project. I guess it's a security issue to use the ** in the vim config? I have both for now, and it is working fine in a mixed C/C++ project. I'm not sure if the uint32_t thing is a bug, but if so does anyone know the appropriate place to report it? |
I think it's not a bug, just the fact that these two combinations of the compiler and the target use different types for uint32_t. In GCC, several bare-metal targets define uint32_t as unsigned long: Xtensa, RISC-V, ARM. This is the case not only in Espressif builds of the toolchain but in the upstream as well. In Clang, the same targets define uint32_t as unsigned.
Could you please give an example of a warning you are getting? Is it from IDF code or from the code in your application? |
Yeah, I think "bug" is a too harsh a term, but maybe "undesired discrepancy" is what I was thinking. I did find one discussion somewhere (can't find the link at the moment) about whether it is a bug or missing feature that the query-driver option doesn't also include these compiler intrinsic/builtin definitions. It was my understanding that the compilers can define things this way, but they should act the same way as though they were defined in a header. With that understanding it would make sense to include these definitions when querying the other compiler.
Interesting, I guess I somehow managed to unwittingly get myself into a uint32_t == unsigned int bubble at my last job. Their arm compilers were updated to use clang years ago, and much of my development has been on their Tiva micros. I also have not done much printf() debugging using fixed-width types on embedded systems in general until working on some ESP32 projects at my new job, and on PCs gcc uses uint32_t == unsigned int. And the icing on the cake is that the ESP experience I did have from years ago was before you guys changed the definition to be consistent with other platforms. I happened to stumble upon your informative comments in this github issue. Now it all makes sense why so much code was using the wrong printf format specifiers.
This is an interesting discrepancy. Do you happen to know why they differ in this area? I'm curious. I could see it making sense to target consistency with larger architectures.
It is from my code in all ESP_LOGX() calls using 32-bit types. The usual The project-specific .clangd CompileFlags solution works perfectly fine for this. I don't intend to migrate to clang for any existing projects. I will start using PRId32 and other standard macros for printf formatting, though, as ugly as they are. |
Hi all, I'm targeting esp32c3 and followed most of the configs above, but somehow I'm still getting an error on freertos include that says I went into I'm using the .vscode/settings {
"clangd.arguments": [
"--query-driver=/home/me/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20240530/riscv32-esp-elf/bin/riscv32-esp-elf-*",
"--background-index"
]
} .clangd CompileFlags:
Remove:
[
-fno-tree-switch-conversion,
-mtext-section-literals,
-fstrict-volatile-bitfields,
-mlong-calls,
-fno-shrink-wrap,
-march=rv32imc_zicsr_zifencei,
] cmakelists.txt cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) |
Do you have a compile_commands.json in your root directory? |
Yeah, the compile commands are automatically generated inside the |
No, it is not. You need to copy/symlink CompileFlags:
# adjust for your compile_commands.json location
CompilationDatabase: build/Debug |
Update: I tried the same setup on a linux box and it works fine. So, I'm thinking maybe it's only on macos. |
Has some progress been made? Is there an official guide on a setup for neovim? |
I got neovim with lsp/clangd running just fine with my esp8266/freertos setup. The trick was to get the clangd from espressif repo exactly as @tolgraven described. I didn't even need to have a custom .clangd The missing bit for me was the
The fun part is that it doesn't seem to need any IDF environment variables to resolve includes and all the paths |
Problem
I have tried to index an example project (uart_echo_rs485) without success. Here are the steps to reproduce (${IDF_PATH} is where the release/v4.3 have been cloned and installed):
The last command should not print
0 .ccls-cache
as the cache should not be empty.Solution
I would love to use
ccls
to index my esp idf project, or any other language server.Alternatives
I haven't tried
clangd
.The text was updated successfully, but these errors were encountered: