Aucoda: Auxiliaries for Compilation Database Projects

自己写了一个包,目前自己用是没问题了,用来干什么的话,题目写得很清楚了。

最开始是用cquery的时候,cquery还没能补全头文件,所以我一直是用cquery-file-info获取命令再把结果传递给company-c-headers来补全的。之后cquery加入了头文件补全,不过体验没company-c-headers好,我就一直用着这个配置。

不过cquery取消了对命令行的传递,理由是大项目可能爆内存。所以我想,自己需要的东西应该自己控制。

同时我从lsp-mode转到了eglot,默认是版本控制确定项目根目录。但是我的项目一般只用版本控制管理源文件所在的文件夹,其它事情一律在父文件做。所以,我又写了一个定位项目根目录的函数。

我想差不多可以独立一个包出来了,于是就写了aucoda

下面是一些特色:

查找文件的时候会在父文件夹没找到时查找兄弟文件夹,这样需要查找的文件可以位于构建文件夹。也可以自定义查找文件的函数(详细看代码的注释和代码)。

对于项目,查找的结果始终是缓存的,对于从中提取出的编译命令,结果是最近最少使用方法缓存的。

提取编译命令时,由于头文件可能不在compile_command.json里面,或者文件是新创建的,所以没找到时文件时采纳最长匹配前缀的文件所使用的命令。

手动区分了objective-cobjective-c++

之所以是对 compilation database 的辅助,还有一个原因是很多基于clang的软件会把自己参数--后跟的结果传给clang,而这个包提取的编译命令可以直接接在--后面。

说了这么多,其实我用到的功能就两个,可能没什么卵用,不过万一有人用呢。。。

对了,clone 的话用 https。

更新:

当前的 LRU 可能会有颠簸,一种比较合理的方法可能是当在某一个 buffer 停留了一定时长之后重新调度一下。我有空就改。

2 个赞

会生成 compile_command.json 吗?工作上有些很旧的环境,没法按照比如 ccls wiki 的方法生成,无奈。

指的是cmake版本过低吗?这种情况试过bear没有?或者bear装不上?

没有 CMake , 用的还是 GCC 4.x ,试过编译 CMake 没有成功(不支持 C++11 ),所以 Bear 还没机会编译 :frowning:

那确实不行,不行的话,我觉得生成compile_commands.json最靠谱的方式还是用ptrace跟踪execve系统调用。这个确实一个C源文件就搞定的事。。。

不过ptrace我还没玩过,有空试一下。。。

不支持 C++11 的话,可以先编译 Clang 3.4.2,这是最后一个用之前的 C++ 版本写的 Clang (应该),支持所有C++11。

看到那個args->args_hash改動後:

2018-08-17: me: Hash argument lists in IndexFiles

2018-08-18: me: But the argsargs_hash comes with a downside: clients can get args and invoke some tools with the full command line. Prefix merge combined with suffix merge might be better.

2018-09-28: me: Your changes are eventually noticed by others :slight_smile:

2018-09-28: PR author: Haha you called it!

不过 cquery 取消了对命令行的传递,理由是大项目可能爆内存。

這點其實不準確。記憶體用的最多的是80% hardware_concurrency()執行緒平行索引專案時,所有compile_commands.json entry args內節省一些,但不是最重要的。

所以在ccls裏,儘管我知道去掉args能節省記憶體,但一直沒去掉((ccls-file-info)一直可用),後來做了一下std::string的internalize (elisp intern)到const char *

cquery支持#include補全,很早就有了,2017-05

另外clang 8的話,clang -cc1 -fsyntax-only -code-completion-at=a.cc:1:10 自帶include completion,但只能一級一級補全,不能一次性補全出dir0/dir1/dir2/file.cc,我不清楚會怎麼傷害可用性。

不过体验没 company-c-headers 好,我就一直用着这个配置。

詳細說明一下?加點截圖之類?

週末我發現可以用CodePatterns補全

screen

但是不要補全placeholder (header>部分),輸入"<後再補全filename部分。

我用completion.include.blacklist (cquery是completion.includeBlacklist)過濾掉一些不想要的條目:

  (setq   ccls-extra-init-params
   `(:completion
            (:include
             (:blacklist
              ["^/usr/(local/)?include/c\\+\\+/[0-9\\.]+/(bits|tr1|tr2|profile|ext|debug)/"
               "^/usr/(local/)?include/c\\+\\+/v1/"
               ]))           ))

現在感覺還行。

没有 CMake , 用的还是 GCC 4.x ,试过编译 CMake 没有成功(不支持 C++11 ),所以 Bear 还没机会编译 :frowning:

clang 4大約(精確:⚙ D27140 Allow clang to write compilation database records)可以用-MJ foo.json,但要自行echo '['; cat *.o.json; echo ']' > compilation_database.json拼接。

我现在已经没用lsp-mode了,图就不贴了,eglot配合201808的cquery时,头文件是没有补全的。

我记得今年初好像是没有头文件补全的,你不是说你不喜欢他们那种手动调用cc -E -v - < /dev/null的形式吗?

最开始的补全是从#开始的,然后直接补完所有的系统目录(现在好像改了,不过现在存在的问题可以去看他们的 issue)。

company-c-headers就是一级一级的补,全部补完那得搜索多少文件夹啊。。。而且..要不要搜?

company自带了几个后端,好像有可以补全预处理命令的(我有段时间体验过)。不过我当时没看具体是哪个,现在我把eglot用的capf放在可前面,好像把之后的覆盖了,或许应该把那个找出来和capf做一个组。。。

误了,应该是lsp-mode提供的。。。

可以试试 https://github.com/nickdiego/compiledb

感谢 @riatre 提供方法,但最终由于 pip 及其依赖无法安装,只能放弃。(环境还真是恶劣)

最后我想到可以自己解析 make 输出,组装为 json 文件,简单无依赖 :slight_smile:


ccls 跑起来了,但无法提供补全, @MaskRay 请教下可以如何排查?我把工程相关的依赖拷贝到一个 fedora 27虚拟机,工具链比实际的编译环境要新很多,可能编译有些问题。

第一次见到连 pip 都没有的平台…… setuptools 也没有吗?还是说干脆就没有 Python?

IDA Pro捆綁libpython*.so就是連pip都沒有的平臺XD

几番折腾,最后通过把 compile_commands.json 中的命令,改为使用 clang 来编译;排除掉编译错误之后, ccls 有补全返回了。

但是, eglot 看样子不支持 GBK 的文件编码(或者是 json ?),等下回再解决 :frowning:

有 python ,但是没有 pip ,也连不了网络。。。

最后我想到可以自己解析 make 输出,组装为 json 文件,简单无依赖 :slight_smile:

如今 compilation database 的应用越来越广泛了, CMake 构建的项目天然可以生成这玩意,但是 GNU Make 的项目就没法直接生成了,而很多项目还是基于后者来构建的。

而针对 GNU Make 的解决方案,基本上就是 Bearcompiledb 这两个项目了,前者使用 C++ 编写,采用 CMake 构建(有点“死循环”了);后者采用 Python 写的,可以用 pip 安装。虽然 compiledb 安装比 Bear 要简单多了,但在公司环境有时候还是安装不上。

最近想到用 web 的方式会比较易用,没有依赖,对当前的编译方式没有任何要求,就做了一个简单的服务,把 make --print-directory -n 的输出解析成 compile_commands.json 文件,服务在:

当前只识别 C/C++ 文件的编译,计划添加替换(比如路径,解决编译环境与开发环境不同的问题)功能,但还没实现。如果有同学用得上,欢迎使用 & 吐槽。