Od dawna słyszałem, że Clangd jest lepszy niż IntelliSense. Ale co to właściwie znaczy lepszy? To przecież tylko opinia. Postanowiłem to sprawdzić. W poniższym tekście opisuję, jak zamieniłem IntelliSense na Clangd i jakie były tego efekty.
Podczas pracy nad projektem na nRF z Zephyrem przy użyciu Visual Studio Code wpadliśmy na pomysł: A może by tak zamienić IntelliSense na Clangd? Czy warto spróbować? Teoretycznie oferują to samo, tylko w inny sposób. Postanowiłem zobaczyć, czy faktycznie warto.
Podmieniamy IntelliSense na Clandg w VSC na Zephyr RTOS.
IntelliSense -> Clang
No to zaczynamy.
1) Dodaj konfigurację wtyczki clangd do settings.json:
2) Jeszcze plik konfiguracyjny projektu w głównym katalogu projektu. Plik musi mieć nazwę “.clangd” a jego zawartość to:
3) Zainstaluj wtyczkę clangd w swoim VSC:
Wtyczka powinna zainstalować clangd jeśli nie znajdzie go w PATH, albo w katalogu podanym w punkcie 1 ("clangd.path": "/usr/bin/clangd").
4) Zainstaluj wtyczkę clangd w swoim VSC:
Teraz ciesz się autouzupełnianiem, rozpoznawaniem ścieżek, informacjami o obiektach i sprawdzaniem kodu w czasie edycji.
I to w całkiem miłej dla developera formie:
Troubleshooting
Tutaj przedstawiamy przykład konfiguracji dla procesorów nRF i Zephyra, ale po wprowadzeniu drobnych zmian, to podejście będzie skuteczne również w innych przypadkach.
Podczas pracy z Zephyrem warto dodać dodatkowy plik konfiguracyjny, który będzie miał zasięg globalny. Plik .clangd
umieszczony w głównym katalogu projektu będzie działać na wszystkie pliki znajdujące się poniżej w strukturze katalogów. Możesz mieć różne konfiguracje dla różnych katalogów, po prostu umieszczając w nich oddzielne pliki .clangd
. Jednak gdy zaczniesz przeglądać pliki źródłowe Zephyra poza swoim projektem, ta konfiguracja przestanie obowiązywać. Przykładowo, po otwarciu pliku kernel.h
z katalogu Zephyra mogą pojawić się błędy.
Wszystko dlatego, że clangd nie rozumie argumentów kompilatora naszego projektu, a powyżej pliku “kernel.h” nie ma żadnego pliku “.clangd”, który by mu je kazał zignorować. Globalny plik konfiguracyjny nazywa się z jakiegoś powodu inaczej: “config.yaml”. Jego lokalizacja zależy od systemu operacyjnego:
- Windows:
%LocalAppData%\clangd\config.yaml;
- Linux:
~/.config/clangd/config.yaml;
Skopiuj zawartość swojego pliku “.clangd” do “config.yaml” i problem będzie rozwiązany.
Możesz szybko uzyskać dostęp do obu plików konfiguracyjnych w Visual Studio Code, naciskając [CTRL+SHIFT+P] i wpisując “clangd: configuration”.
Aby zewnętrzne narzędzie dobrze radziło sobie z analizą kodu C/C++, musi "wiedzieć" to samo, co kompilator. Oznacza to znajomość, w jaki sposób każdy plik jest kompilowany (z jakimi flagami, includami itp.) oraz "wewnętrzne" elementy toolchainu. Dostarczamy te informacje, podając:
- Ścieżkę do
compile_commands.json
(w parametrze:--compile-commands-dir=${workspaceFolder}/build
); - Kompilator/toolchain (w parametrze:
--query-driver=${env:ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi/bin/arm-zephyr-eabi-*
- dzięki “*” clangd sam dobierze, czy ma to być arm-zephyr-eabi-gcc, czy g++);
Oczywiście, ścieżki można podać jako absolutne, ale w przyszłości trzeba pamiętać o ich aktualizacji, jeśli zmienimy toolchain lub katalog wyjściowy.
Konfigurację wtyczki clangd możesz zrobić też przez GUI:
W pliku “.clangd” możemy też suppresować błędy, nawet dla pojedynczych plików lub grup. Przykład:
Oczywiście, pamiętajcie: "Don't shoot the messenger".
Ważna uwaga
W przypadku naszego projektu opartego na NRF SDK v2.6.1, najnowszy clangd (v1.8.3) wyrzucił z listy inkludowanych katalogów “...arm-zephyr-eabi/12.2.0/include/”. To uniemożliwiało znalezienie niektórych plików nagłówkowych Zephyra (błąd: In included file: 'stddef.h' file not found). Zalecam więc instalację wersji np. 17.0.3 - w tej wersji nie mieliśmy tego problemu.
Co zrobić, jeśli coś nie działa?
1. Przestaw poziom logowania z --log=error
na --log=verbose
(w konfiguracji wtyczki clangd lub w settings.json).
2. Otwórz jakiś plik .c/.cpp, żeby clangd miał co analizować.
3. Otwórz “Output” wtyczki clangd:
4. Zrestartuj clangd wciskając [CTRL+SHIFT+P] i wpisując “clangd: restart”:
5. Zobacz na początek, czy clangd dostaje poprawne parametry:
Sprawdź też ścieżki w logu i porównaj te z compile_commands.json.
I to wszystko.
Podsumowanie
Po zmianie IntelliSense na Clangd zauważyliśmy kilka istotnych korzyści:
- Skuteczniejsze zrozumienie języka: Clangd lepiej rozumie strukturę i hierarchię kodu, co pozwala na bardziej precyzyjną analizę.
- Lepsze wsparcie dla hierarchii: Możesz łatwiej zobaczyć strukturę i zależności w kodzie.
- Szybsze podpowiedzi i automatyzacja: Clangd natychmiast informuje o brakujących includach lub automatycznie je dodaje, co przyspiesza pracę.
Te zmiany zdecydowanie usprawniły naszą pracę i poprawiły efektywność kodowania.
Clangd ma wielu fanów w GoodByte, więc może i Wy poświęcicie dzień lub dwa, aby się z nim zapoznać.
To naprawdę fajne narzędzie. Serio.