ccls/clangd C/C++補全,及近況更新

這段時間hack radare2比較多,把ccls補全的改進又拖了好久。C/C++的補全大家應該一致認爲clangd最快吧?ccls/cquery/irony都慢些。clangd補全有很多啓發,有一些有價值的部分,但我覺得對於通常的程式碼庫很多是用不着的。它的速度快是因爲ccls/cquery有一些細小的方面沒有注意。

今天看了一點clangd的補全處理方式,感覺可能有兩點:

  1. 用了clangd::buildPreamble,在stale情況下也會使用clangd::(anonymous)::ASTWorker::getPossiblyStalePreamble
  2. clang::FrontendOptions::SkipFunctionBodies = true;

現在ccls master branch用:

--- a/src/clang_tu.cc
+++ b/src/clang_tu.cc
@@ -109,9 +109,10 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
         /*CacheCodeCompletionResults=*/true, g_config->index.comments,
         /*AllowPCHWithCompilerErrors=*/true,
 #if LLVM_VERSION_MAJOR >= 7
-        SkipFunctionBodiesScope::None,
+        diagnostic ? SkipFunctionBodiesScope::None
+                   : SkipFunctionBodiesScope::PreambleAndMainFile,
 #else
-        false,
+        !diagnostic,
 #endif

懷疑這個能改進速度,歡迎測試~(另外現在會在/tmp/preamble-*下堆臨時檔案,這些是clang::PrecompiledPreamble::TempPCHFile。如果在ccls/src/clang_tu.cc中做如下修改:

    Unit.reset(ASTUnit::LoadFromCommandLine(
...
        /*CaptureDiagnostics=*/diagnostic, Remapped,
-        /*RemappedFilesKeepOriginalName=*/true, 1,
+        /*RemappedFilesKeepOriginalName=*/true, /*PrecompilePreambleAfterNParses=*/0,
        diagnostic ? TU_Complete : TU_Prefix,

可以阻止生成/tmp/preamble-*,但補全會慢很多(這一點也歡迎測試~)。正在努力學習clang,爭取讓ccls像clangd那樣用上PrecompiledPreamble::Buildbool StoreInMemory

另外,我需要仔細思考是否每個textDocument/didOpen開的檔案需要comp-query diag-query兩個分開執行緒構建ASTUnit。這樣浪費記憶體但可能能降低補全延遲。

最近關於ccls的新聞:

  • $ccls/memberHierarchy也加了:flat t,可以快速列示struct/class/union的成員。 我現在用
(lsp-ui-peek-find-custom 'base "$ccls/memberHierarchy"
                           (append (lsp--text-document-position-params) '(:flat t)))

lsp-mode作者剛剛merge了lsp-find-custom,也可以用這個,如果你們更習慣ivy-xref/href-xref的話。比如 @amosbird 大大應該是這樣的。

  • 有兩個人問起ccls/cquery這套能否用到Swift上。我肯定不會做Swift這種這麼不general的東西😜index-store-path不知道要猴年馬月了
  • 傳了LanguageClient-neovim的幾張截圖,還嘗試在r/vim 佈道,但沒有起到傳播效果😭https://www.reddit.com/r/vim/comments/99utc7/ccls_languageclientneovim_custom_cross_references/
  • Arch Linux aur/ccls-gitarchlinuxcn/ccls-git SIGSEGV修復了,因爲extra/clang用了-DLLVM_ENABLE_RTTI=ON而ccls默認用了-fno-rtti導致的。詳見https://github.com/MaskRay/ccls/issues/30#issuecomment-415594762
  • 我在eglot issues裏評論了一些(乘機加入ccls私貨)……希望作者會想起來往README.md裏也加上ccls…………(大家如果稍微吹吹風我也會很開心…)
    • 跳轉到專案外檔案 lsp-ui-peek--goto-xref加了個lsp--cur-workspace傳播解決的,我自己用起來很舒服。如果方案如果能夠改進,歡迎貢獻lsp-mode lsp-ui eglot啊
    • remote project這個真的是痛點。我也很希望支持。但現在的辦法是保持remote/local路徑一致,把remote .ccls-cache同步到本地。
  • Doug Schaefer來光顧了,他是Project Lead of Eclipse CDT。如果他滿意,並且他在 EclipseCon Europe 2018有宣講的話,也許能讓他提到ccls (盡力而爲)……感覺他可能在Windows鏈接clang/llvm C++有困難。確實,Windows上cquery好用很多,理由是Windows releases.llvm.org有libclang所需的header和library,而Clang C++ headers是缺的。如果有人願意折騰下msys2 clang+llvm構建ccls,貢獻一下wiki (publicly editable)我會感激~~
13 个赞

reddit 上面的用户关注点好奇怪,看起来 vim 硬核用户似乎不屑于使用名字带 neovim 的插件。

1 个赞

感謝~你這個看的人就比我的custom cross references多……大家更關心補全而不是xref…

給ccls加了StoreInMemory PrecompiledPreamble,不會再生成/tmp/preamble-*了,另外補全速度會快些。如果用clang 7/trunk,會比clang 6快點。

1 个赞

更关心补全而非xref

可能是说明写代码的人多 ,看代码的人少

其实很多写(其实是改)代码的地方也要用到xref。

昨天试了一下跨文件查找,在查找的地方改,跳转的时候就是用的xref。

类似的需求应该不少。

剛剛改進了textDocument/publishDiagnostics(textDocument/didChange觸發),flycheck on-the-fly diagnostics產生延遲應該降低不少(因爲復用了上一次保存後構建的PrebuiltPreamble,補全也是用這個)

1 个赞

正在折腾ccls on MSYS2,因为公司缘故,被迫在windows开始开发……

合併了一個Riatre的 Normalize paths on Windowshttps://github.com/MaskRay/emacs-ccls/issues/10 似乎也有希望解決。

折騰出MSYS2 gcc編譯ccls、鏈接msys2 clang(用它的庫,而不用它的compiler)後在wiki上描述一下怎麼做吧~

另外,不能用msys2 clang編譯ccls,有兩個bugs

另外今天的主要更新是把textDocument/signatureHelp也改寫成clangd式樣的Clang C++ API形式了,但保留了cquery的cache模式。

textDocument/completion也翻新精簡了

2 个赞

0.20180812 之后在无法在 el capitan (macOS 10.11) 下编译通过了:

Last 15 lines from ~/Library/Logs/Homebrew/ccls/02.cmake:
[ 41%] Building CXX object CMakeFiles/ccls.dir/src/query.cc.o
/usr/local/opt/llvm/bin/clang++  -DDEFAULT_RESOURCE_DIRECTORY="R\"(/usr/local/Cellar/llvm/7.0.0/lib/clang/7.0.0)\"" -I/tmp/ccls-20180922-8715-19vn0sx/src -isystem /tmp/ccls-20180922-8715-19vn0sx/third_party -isystem /tmp/ccls-20180922-8715-19vn0sx/third_party/rapidjson/include -isystem /usr/local/opt/llvm/include  -DNDEBUG   -fno-rtti -Wall -Wno-sign-compare -std=c++17 -o CMakeFiles/ccls.dir/src/query.cc.o -c /tmp/ccls-20180922-8715-19vn0sx/src/query.cc
/tmp/ccls-20180922-8715-19vn0sx/src/pipeline.cc:104:6: error: 'shared_mutex' is unavailable: introduced in macOS 10.12
std::shared_mutex g_index_mutex;
     ^
/usr/local/Cellar/llvm/7.0.0/include/c++/v1/shared_mutex:178:58: note: 'shared_mutex' has been explicitly marked unavailable here
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
                                                         ^
[ 43%] Building CXX object CMakeFiles/ccls.dir/src/serializer.cc.o
/usr/local/opt/llvm/bin/clang++  -DDEFAULT_RESOURCE_DIRECTORY="R\"(/usr/local/Cellar/llvm/7.0.0/lib/clang/7.0.0)\"" -I/tmp/ccls-20180922-8715-19vn0sx/src -isystem /tmp/ccls-20180922-8715-19vn0sx/third_party -isystem /tmp/ccls-20180922-8715-19vn0sx/third_party/rapidjson/include -isystem /usr/local/opt/llvm/include  -DNDEBUG   -fno-rtti -Wall -Wno-sign-compare -std=c++17 -o CMakeFiles/ccls.dir/src/serializer.cc.o -c /tmp/ccls-20180922-8715-19vn0sx/src/serializer.cc
1 error generated.
make[2]: *** [CMakeFiles/ccls.dir/src/pipeline.cc.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/ccls.dir/all] Error 2
make: *** [all] Error 2

Do not report this issue to Homebrew/brew or Homebrew/core!


Error: You are using macOS 10.11.
We (and Apple) do not provide support for this old version.
You will encounter build failures and other breakages.
Please create pull-requests instead of asking for help on Homebrew's
GitHub, Discourse, Twitter or IRC. As you are running this old version,
you are responsible for resolving any issues you experience.

sierra (macOS 10.12) 或更新的系统都可编译成功。

感謝報告。<10.12 沒有std::shared_mutex

如果這個太舊的話我就打算算了,macOS用戶更新頻繁的……應該比gcc<7 Linux用戶少很多。不太想加這些兼容代碼……

這部分pipeline.cc我希望越簡單越好,所以最近又再度簡化了一下。cquery import_pipeline.cc和所有相關組件就是太複雜了。(clangd未來如果要引入非當前訪問的buffers的references,如果試圖添加index-on-save,也勢必要增加這個組件。)

最近有一些intern (Lisp intern…)std::string的改動,記憶體節省了很多。

今天把diagnostics整頓了一下。用了debounce,預設一秒內的textDocument/didChange只會parse document一次生成一次textDocument/publishDiagnostics,緩解之前的痛點:diagnostics浪費CPU時間。

  struct Diagnostics {
    // Like index.{whitelist,blacklist}, don't publish diagnostics to
    // blacklisted files.
    std::vector<std::string> blacklist;

    // Time to wait before computing diagnostics for textDocument/didChange.
    //   -1: disable diagnostics on change
    //   0: immediately
    //   positive (e.g. 500): wait for 500 milliseconds. didChange requests in
    //     this period of time will only cause one computation.
    int onChange = 1000;

    // Time to wait before computing diagnostics for textDocument/didOpen.
    int onOpen = 0;

    // Time to wait before computing diagnostics for textDocument/didSave.
    int onSave = 0;

    bool spellChecking = true;

    std::vector<std::string> whitelist;
  } diagnostics;

diagnostics.frequencyMs 刪除了(這個選項cquery也有)。預設不用配置就能獲得較佳的體驗。

这个赞, diagnostics 确实是提升性能的好方法, 要不是平常 diagnostics 消息太多了.

查了一下桌面系统市占率,Linux 这么多年,依然只有程序员在用,macOS 各个版本的程序员用户加起来,应该不会比 Linux 少:

你没有算智能设备

智能设备不算桌面,不然还要把服務器和工業设备加进來。

您好,问一个可能比较基础的问题,我安装了最新的lsp-mode,自带clangd补全,但是无法补全include时的头文件,请问该如何配置呀?谢谢

1 个赞

生成compile_commands.json有很多命令,如bear,scan-build,ninja,waf等,大家一般用的是什么?区别大吗?

它们是不同的构建系统。 cmake最常用于c ++项目

radare2 看的怎么样了?