8

C++ language server ccls一周年

 3 years ago
source link: http://maskray.me/blog/2019-04-01-ccls-one-year
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C++ language server ccls一周年

2018年4月1日我写了ccls: a fork of the C++ language server cquery,宣告ccls诞生。如今一周年,有必要记录下这一年的点点滴滴。

4月1日我fork出来,原因是我需要一个满足自己口味的C++ language server。修改cquery几个月,期间也曾学习过rtags ycmd clang_completer等clang-based工具,对如何打造language server颇有心得。由于和原作者理念差异,在cquery引入很多改动是掣肘的。因为理念不合被取消commit权限,就决定自己新建一个项目。另外cquery作者也在聊天室里提到他一直在等待clangd。而我的感觉是,clangd采用的并非最佳模型,或至少,不应该是用户唯一的选择。其实当时我也试探性想贡献一下clangd的fuzzy matcher,发现想法不合做贡献就要耽误很多时间,很多地方的设计理念也不合。所以还是决定从cquery改,看如何闯出一番天地。当时觉得cquery已经很成熟了(看着它的star涨到超过1000,在LSP、emacs-china等地被人越来越多地讨论,也会有很有成就感(虚荣心)),我另起炉灶也就是自娱自乐而已。

说干就干,从一个描述为“Resurrection of ccls”的commit开始,3月31日提交了8个描述只有一个点的commits(它们改了116个文件!)。接下来在cquery的代码库上做了大量清理工作:删除第三方库、精简代码、删除过度的抽象、合并拆得过碎的文件,当然还有改名、删除waf构建系统、删除无用blob、……自己用得舒服了再推己及人,希望别人也能用上满足自己的虚荣心。其实说穿了就是和cquery/clangd抢夺用户。精简并不能改变用户习惯,带来用户。我很快瞄准了cquery用户的一个痛点:auto-index pipeline的稳定性。最大的问题是,保存文件后容易导致重复或丢失的references。如果.h.cc没有放在同一个目录,更容易出问题。

这个组件我一直知道被设计得过分复杂,但我自己对这部分理解也不透彻。cquery把索引信息分成并行索引时用的IndexFile和加载到全局数据库里的QueryFile是个非常不错的设计。一个文件修改,触发索引,获得IndexFile,合并回主线程的全局数据库的过程其实很脆弱,出过很多问题。在交叉索引信息的基本单元(标识符,由Clang Unified Symbol Resolution表示)的表示从字符串改为8字节hash后,pipeline中的几个步骤已经没有太大意义了。query.cc用的MergeableUpdate也是有问题的。能改善一点性能(indexer threads分担少量main thread任务),但cquery的全局索引更新模型是不满足交换律的,这么做也会在一些情况下会导致索引丢失,这里还有个merge sort用的merge的bug,直到7月才修好。

五月初我把pipeline翻新了。初时内存占用会稍高,但稳定性提升很多,不会发生保存多次导致索引确实或重复的问题。到9月已经非常稳定了。

等到逐渐有人关注了,有时候不得不回答一些讨厌的问题:和cquery的区别是什么、有cquery/clangd(clang官方项目)为什么还要弄ccls。我现在仍然讨厌这类简短而内容空洞问题(除非提问者能证明自己思考过了)。在此引用eglot作者João Távora的话,当别人问起有lsp-mode为什么还要再造一个client时,他回答:“You see, I added those paragraphs in the first place because some people ask, sometimes indignantly, why I write new things and don't contribute to an existing project. Apparently "because I want to" and "to have fun" aren't acceptable answers. But for me, they are still totally great answers, so if you are having fun writing lsp-mode.el I can only wish you well.”

ccls对于我的价值:

  • 最重要的是给了我好好学习clang的理由。2017年给llvm全家桶贡献了几个patches,到年底依然只有10个不到,后来慢慢在这个领域找到兴趣。维护ccls能逼迫我认真钻研clang工作机制,以及多灌水(commit)。到现在,在clang里灌了69个,llvm其他地方都加起来灌到400多。
  • 迫使我了解Language Server Protocol各个方面的细节。说实话,我不喜欢这个协议,很多地方设计得过于臃肿、浪费,为了所谓的VSCode兼容性做了很多让客户端、服务端都痛苦的设计。其实无可厚非,这个协议本来就是Microsoft用于VSCode的,由于用户的请求才被开源出来,这和LLVM、Rust那些社群的管理模式是很不一样的。话虽如此,比起之前几代产品还是好不少,汇聚起来了一个真正帮用户改进编程体验的松散的社群。
  • 一个展示平台。
    • 被队友、对手、主办方(??)自发关注到(尤其是DEF CON 26 CTF上)。在LLVM Dev Meeting上一些闲聊的人谈到。
    • 有厂商想给我donation但我没要。
    • 有厂商想用ccls做离线分析。
    • 被spacemacs doom-emacs采用。进了v8的.gitignore
    • 有人给AOSC、Mac OS X Homebrew、FreeBSD、Nix、Void Linux、Fedora等打包。另外还有我自己给Arch User Repository贡献的。
    • 被GNU make维护者Paul Smith使用了。help-make是我订阅过最久的邮件列表,看完过Managing Projects with GNU Make。OI比赛时我也是用GNU make编译程序、运行测试的。这个带我的感觉很不一样:一直以来写的软件影响着你的人,现在也被你影响了。
  • 有朋友真的会关心我这个东西做了怎么样,和我探讨实现。

2018年7月初从“First draft: replace libclang indexer with clangIndex”开始,用Clang C++ API重写了indexer。接下来把project.cc中用的libclang compile_commands.json解析换成clangTooling。随后用Clang C++ API重写了completion/diagnostics(从clangd和ASTUnit学了很多)。最后终于把所有libclang组件移除。

用了libclang很久,发现了它的很多问题。它在早年clang API不够稳定时确实立下了功劳,最初应该是Apple Xcode用,后来催生了clang_completer、rtags、irony-mode、iycmd clang_completer等工具。但它的限制也很明显,Clang C++ API茫茫多,libclang作为稳定的C API包不完API,因此它只实现了一些较高层次的API,某些API如(find declaration, find definition)实际上包含了很多逻辑,如果使用场景和API设计者不同,就会发现很不灵活。

10月把以前移除的textDocument/documentLink textDocument/rangeFormatting等小众功能都加了回来,在功能上也不输了。

最近几个月都挺头疼的,日均一个新增issue。不少issue提问的人随手一写,好在最近引入了GitHub issue template情况有所改观,但依然能注意到非常多不懂脑筋的人,让我很反感。我对于issue管理比较粗暴,通常回复一下就关闭,不会像一些其他项目会等一段时间,关闭时再回复一句话抚慰提问人。我不愿意浪费这些时间。别人也许会这么评价:“It did spawn a fork: https://github.com/MaskRay/ccls, which is actively developed, but the lead is explicitly not interested in supporting community requests, which IMO bodes well for its longevity.”我觉得这挺贴切。我也很感谢即时的反馈,比如某个改动造成了某某发行版编译失败或运行错误,现在都能较为迅速的得到反馈及时改正。有时用户会注意到clang bugs,调试它们的过程也挺有趣。

一些有趣的issues:

  • https://github.com/MaskRay/ccls/issues/30 -fno-rtti导致的ABI mismatch。终于查明了aur/ccls-git会segfault的原因。有个相关的commit让我成了GCC contributor:)
  • https://github.com/MaskRay/ccls/issues/71 GCC 5 dual ABI导致的ABI mismatch。
  • https://github.com/MaskRay/ccls/issues/186 调整wiki结构。新的结构确实更清晰了,不过我吐嘈刚改完的样子有些罗嗦……现在比较简洁了。很多项目的文档我都觉得太长不想读。
  • https://github.com/MaskRay/ccls/issues/355 根据lib{clang,LLVM}*.a获得.so

20180513的“Congratulations to Tea Deliverers”(恭贺Tea Delievers再度入围DEF CON CTF决赛),20180521的“Maker Faire”,20180731的“Real World CTF”(给本来宣传力度就很大的活动造势)。

Share Comments


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK