ccls: a fork of the C++ language server cquery

感觉很矛盾,一方面希望自己做的东西能有广泛受众(比如一个学长因此找到了我),另一方面,项目关注多了issue也多了(没有建设性/用户错误也多了,我真的很想叫这类issue愚蠢),之前三个月每天看cquery issues很劳累。

现在更多地考虑是自己用着舒服,当然如果能不费太大工夫帮到其他Linux/FreeBSD用户,或是我自己也想尝试知道的一些奇异的配置如cross compiling,我也会愿意做的。有近500个commits加做了大力推广,我确实是居功自傲,但原作者伤人的不仅仅是改变了协作模型,不多提。想到这篇文章会被别人翻译着看挺高兴的呢~LanguageClient-neovim cquery方法、lsp-ui一些东西(主要作者sebastiencs,我早期也做了一点修补)、Wiki、Reddit推广、spacemacs +tools/lsp加已放弃的+tools/cquery(已经转投doom-emacs~)、langserver.org、推动Arch Linux/FreeBSD包、……

Good Friday

如果是今年一月cquery还有很多问题时发生这个变故,我肯定会毫不犹豫fork自立门户再试图超过它。但现在我想不出更加革新性的功能增强,libclang索引的上限我也有所了解,我也没那么多精力在空闲时间再做更多事。前些时候commits多是因为对交叉引用功能不满+拿这个项目学习C++,懂得了一些犄角旮旯的知识。比如clang 3.5推导lambda return type的缺陷,copy initialization用move structor clang 3.9之前的缺陷……玩generic lambda等。

clangd主要开发的人面向超大代码库和Chrome,但他们的方向感觉不对劲,加之code review,一些简单功能也非要用大量代码实现。到现在还在用AST的方法蛮干,没有合适的内存内交叉索引数据结构。现在开始又多了些workspace/symbol等功能,未来重构这些添加的方法只会增加重复劳动。

自己做主,主要为自己服务,就能作出很多cquery难以做的选择:

  • -std=c++17,向telegram-desktop看齐,可以删除variant optional string_view的third-party依赖。用clang++ 6.0.0和系统libstdc++ (gcc 7.3左右)需要这个补丁使得std::get<...>(std::variant<...>)可用。https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/std/variant?view=markup&pathrev=258854
  • 抛弃textDocument/documentLink textDocument/rangeFormatting $cquery/wait等几乎没用的功能。把.h函数定义放到.cc里这类refactor功能clang-*等外部工具能做的,不值得在language server中实现。这些功能未来会形成命令行/clangd refactor框架,libclang可能永远做不了这些事。
  • 删除默认的-fms-compatibility -fdelayed-template-parsing -fms-extensions。这是原作者revert我的一个commit
  • 删除"command"/"arguments"中对compiler scheduler goma clang的特判。提供给libclang的命令行应该做尽可能少的变换,用户自行添加选项适配自己的项目。
  • src/下文件实在太多了,很多东西几十行就写成一个新文件。不必要的东西我删除了一些。
  • 修了一个/usr/include/c++/7.3.0/是指向/usr/include/c++/7 symlink时,跳转到系统头文件没有索引信息的问题。
  • #include ""不补全STL。""中包含系统头文件合法,但是不符合规范。
  • 可以用C++ optional TS filesystem代替各类hack的文件系统函数。
  • 放弃#include <c*>转用C风格#include <*.h>。我比较懒惰,想省std::等几个字。
  • stdio,抛弃iostream

import_pipeline file_contents file_consumer等文件,我也比较茫然,每次要改都得重新理论下。这里流程太复杂了,不清楚能怎么简化。

不知道这个项目我能坚持到什么时候,使用请注意风险~

Resurrection Sunday

Building trunk libclang

  • CXSymbolRole: read/write/addr references
  • clang_File_tryGetRealPathName: on Arch Linux, system header include paths extracted from clang -E -v -xc++ /dev/null have several ../ path components, which confuse clang_getFileName. You'll need clang_File_tryGetRealPathName to correctly resolve paths of system C++ headers.

They require #if CINDEX_VERSION >= 48, while CINDEX_VERSION shipped with clang 6.0.0 is 45.

Here are instructions to build trunk libclang(see https://llvm.org/docs/CMake.html for LLVM cmake options). Note, please use a powerful workstation to build LLVM.

1
2
3
4
5
6
7
git clone https://git.llvm.org/git/llvm.git
cd llvm
git clone https://git.llvm.org/git/clang.git tools/clang
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER=clang -DLLVM_OPTIMIZED_TABLEGEN=On -DLLVM_USE_LINKER=lld -Bstatic-release -H.
ninja -C static-release libclang
# Built static-release/lib/libclang.*

If you want to copy built libclang from workstation to local:

1
2
3
4
5
rsync -a -f '+ lib' -f '+ lib/clang**' -f '+ lib/libclang.*' -f '- *' \
workstation:~/Dev/llvm/static-release/ ~/Dev/llvm/static-release/
# If you want to use trunk clang as the compiler,
# ninja -C static-release clang
# and add -f '+ bin' -f '+ bin/clang' -f '+ bin/clang++' -f '+ bin/clang-7' on the rsync command line

The libclang headers reside in Dev/llvm/tools/clang while built libraries are in Dev/llvm/static-release. Locate them with CMAKE_PREFIX_PATH.

1
2
3
4
5
cmake -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=lld \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DSYSTEM_LIBCLANG=On \
-DCMAKE_PREFIX_PATH="$HOME/Dev/llvm/static-release;$HOME/Dev/llvm/tools/clang" -Brelease -H.
cmake --build release
# Built release/ccls whose path can be used to set emacs-ccls variable `ccls-executable`