自己写了一个包,目前自己用是没问题了,用来干什么的话,题目写得很清楚了。
最开始是用cquery
的时候,cquery
还没能补全头文件,所以我一直是用cquery-file-info
获取命令再把结果传递给company-c-headers
来补全的。之后cquery
加入了头文件补全,不过体验没company-c-headers
好,我就一直用着这个配置。
不过cquery
取消了对命令行的传递,理由是大项目可能爆内存。所以我想,自己需要的东西应该自己控制。
同时我从lsp-mode
转到了eglot
,默认是版本控制确定项目根目录。但是我的项目一般只用版本控制管理源文件所在的文件夹,其它事情一律在父文件做。所以,我又写了一个定位项目根目录的函数。
我想差不多可以独立一个包出来了,于是就写了aucoda
。
下面是一些特色:
查找文件的时候会在父文件夹没找到时查找兄弟文件夹,这样需要查找的文件可以位于构建文件夹。也可以自定义查找文件的函数(详细看代码的注释和代码)。
对于项目,查找的结果始终是缓存的,对于从中提取出的编译命令,结果是最近最少使用方法缓存的。
提取编译命令时,由于头文件可能不在compile_command.json
里面,或者文件是新创建的,所以没找到时文件时采纳最长匹配前缀的文件所使用的命令。
手动区分了objective-c
和objective-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 还没机会编译
那确实不行,不行的话,我觉得生成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 args
→ args_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
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補全
但是不要補全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 还没机会编译
clang 4大約(精確:⚙ D27140 Allow clang to write compilation database records )可以用-MJ foo.json
,但要自行echo '['; cat *.o.json; echo ']' > compilation_database.json
拼接。
MaskRay:
詳細說明一下
我现在已经没用lsp-mode
了,图就不贴了,eglot
配合201808的cquery
时,头文件是没有补全的。
我记得今年初好像是没有头文件补全的,你不是说你不喜欢他们那种手动调用cc -E -v - < /dev/null
的形式吗?
最开始的补全是从#
开始的,然后直接补完所有的系统目录(现在好像改了,不过现在存在的问题可以去看他们的 issue)。
company-c-headers
就是一级一级的补,全部补完那得搜索多少文件夹啊。。。而且..
要不要搜?
company
自带了几个后端,好像有可以补全预处理命令的(我有段时间体验过)。不过我当时没看具体是哪个,现在我把eglot
用的capf
放在可前面,好像把之后的覆盖了,或许应该把那个找出来和capf
做一个组。。。
误了,应该是lsp-mode
提供的。。。
riatre
2018 年10 月 10 日 17:21
8
感谢 @riatre 提供方法,但最终由于 pip 及其依赖无法安装,只能放弃。(环境还真是恶劣)
最后我想到可以自己解析 make 输出,组装为 json 文件,简单无依赖
ccls 跑起来了,但无法提供补全, @MaskRay 请教下可以如何排查?我把工程相关的依赖拷贝到一个 fedora 27虚拟机,工具链比实际的编译环境要新很多,可能编译有些问题。
riatre
2018 年10 月 19 日 15:19
10
第一次见到连 pip 都没有的平台…… setuptools 也没有吗?还是说干脆就没有 Python?
IDA Pro捆綁libpython*.so就是連pip都沒有的平臺XD
几番折腾,最后通过把 compile_commands.json 中的命令,改为使用 clang 来编译;排除掉编译错误之后, ccls 有补全返回了。
但是, eglot 看样子不支持 GBK 的文件编码(或者是 json ?),等下回再解决
有 python ,但是没有 pip ,也连不了网络。。。
最后我想到可以自己解析 make 输出,组装为 json 文件,简单无依赖
如今 compilation database 的应用越来越广泛了, CMake 构建的项目天然可以生成这玩意,但是 GNU Make 的项目就没法直接生成了,而很多项目还是基于后者来构建的。
而针对 GNU Make 的解决方案,基本上就是 Bear 和 compiledb 这两个项目了,前者使用 C++ 编写,采用 CMake 构建(有点“死循环”了);后者采用 Python 写的,可以用 pip 安装。虽然 compiledb 安装比 Bear 要简单多了,但在公司环境有时候还是安装不上。
最近想到用 web 的方式会比较易用,没有依赖,对当前的编译方式没有任何要求,就做了一个简单的服务,把 make --print-directory -n
的输出解析成 compile_commands.json 文件,服务在:
当前只识别 C/C++ 文件的编译,计划添加替换(比如路径,解决编译环境与开发环境不同的问题)功能,但还没实现。如果有同学用得上,欢迎使用 & 吐槽。