如何在 .ccls 中包含 .c 文件?

最近遇到一个问题,就是我看别人的工程文件的时候(编译数据库肯定是没,makefile也没),如果需要一个基础的跳转,.ccls文件怎么写才行。

-Ixxxx这个能把需要的头文件都包含进去,比较容易跳。源文件.c怎么包含进去呢。

我在弄的时候,发现每打开一个.c文件,.ccls-cache里面会生成相关.c文件的缓存,所以能跳过去。 所以我在猜测肯定有相关刚开始就能包含所有源文件的写法,但是找不到相关描述

(Project Setup · MaskRay/ccls Wiki · GitHub)

我的.ccls文件如下

%compile_commands.json
--target=arm-none-eabi-gcc
-I
/usr/include/newlib
-I
./freertos/include/
-D./freertos/list.c

最后一行是有问题的,但是我不知道怎么包含.c文件进去,如果这个包含了,lsp能生成所有文件的.ccls-cache,这样的话效果估计就和vscode一样,能有一个基础的跳转。

  • -I 独占一行不别扭吗?
  • -DMACRO Wiki 已经写得很明白了。
  • 标题「求助,关于xx的问题」指向不明,建议改为「如何在 .ccls 中包含 .c 文件?」
  • 「编译数据库肯定是没,makefile也没」有没有 configure/CmakeLists.txt 之类的生成脚本?
  • 好的,后面改
  • -DMACRO这个网站里面没有相关说明呀,就在example里面提到一下。-DMACRO./freertos/这样写对吗(后面带.c文件路径)
  • 我现在就改
  • 没有,就是keil5的一个工程文件。我是不是得学一下cmake,写CmakeLists.txt,自动生成.json?这个是否适用于任何工程文件场景?
  • 兄弟这么晚还在写代码吗,辛苦了。

-DMACRO 的意思是 -D 后面必需是 Macro,不是用来导入 .c 文件的。

keil 工程应该可以导出 makefile 或者编译命令,在此基础上生成 compile_commands.json。

嵌入式真滴麻烦唉。。。。。我有makefile,但是工程里面的.ld文件,.s文件,还有库里面的某些汇编都要改,keil工程和makefile工程差别挺多的。所以才来问。

我的也是嵌入式工程,而且编译器还是厂家规定的(只给了我们win下的编译工具链),幸好厂家有给配置了一套codeblocks的项目,可以编译通过的。

然后我就在codeblocks的编译日志输出窗口里看见了编译过程的各种-I -D,提取出一份不重复的放到.ccls里就行了,没有用到compile_commands.json.

受限于编译器,我代码在win下,编译器也是win用的,而为了emacs我就要用wsl(同样配置,win版emacs启动8秒,wsl1版4.3秒,linux原版0.8秒), 还不能用wsl2(跨文件系统IO性能比wsl1差),总之就是各种苦难。

废话少说,下面是我的.ccls写法:

/c/chain/bin/clang.exe
-includexxxxyyyy/src/myinclude.h
-g
-Oz
-mllvm
-flto
-fno-common
-integrated-as
-fms-extensions
-Wno-shift-negative-value
-Wno-undef
-DEVENT_HANDLER_NUM_CONFIG=2
-DEVENT_TOUCH_ENABLE_CONFIG=0
-DEVENT_POOL_SIZE_CONFIG=256
-DCONFIG_EVENT_KEY_MAP_ENABLE=0
-Iapps/common
-Iapps/common/audio
-Iapps/common/audio/encode
-Iapps/common/audio/stream
-Iapps/common/config/include

只是为了演示,删减了很多。

首先第一行,是指定编译器的路径,这里我是指定厂家给的编译器的安装路径在wsl下的形式,一般应该是/盘符/路径/文件这样的形式,当然了,如果你确实不知道,直接写clang放第一行就行了。

然后是-includexxxxyyyy/src/myinclude.h这个是由于ccls有时候分析不了我间接include的某个头文件,导致语法分析有些问题,干脆就直接指定让它包含xxxxyyyy/src/myinclude.h这个头文件了。

然后是一些编译flags,这些看你实际情况,一般不写也没问题,写多了也会有问题,这里我-Wno-undef只是为了忽略一些编译警告。

然后是一堆-D宏名,这是直接告诉ccls,这些宏的定义,它分析代码的时候相当于看见了#define 宏名

最后是一堆-I头文件搜索路径,分析代码的时候看见#include “xxxx.h”,就会从头文件搜索路径里找这个 xxxx.h

.ccls里是不必写.c文件的,我上面这样设置,所有.c文件都被解析了生成到.ccls-cache缓存里

1 个赞

我当时是手动解析viual studio 的工程(xml)文件,然后生成相应的编译数据库。我觉得你们可以试试这个思路自己写个工具。还是挺简单的。我用了好几年都一直能满足我的需求。

后来研究一下codeblocks的项目文件.cbp,发现里面已经有所有-D,-I所需的参数了,所有需要编译的.c文件也列在里面,想要生成compile_commands.json的话,写python来分析.cbp文件,再按json文件要求的json形式填充各种属性,最后输出json文件就好了。

再后来发现厂家其实有提供makefile,然后不知道从哪里搜索到可以make -Bnwk,输出编译过程的所有参数,用python处理一下同样可以按要求生成compile_commands.json

我也看过 Compilation database — Sarcasm notebook 可能我使用不当,在win下,没一个好使的。

即使厂家专有的工具,通常也具备导出 makefile 和编译命令的功能。.ccls / compile_commands.json 无非也就是编译命令参数。

有的构建工具能生成 compile_commands.json,你就可以在 .ccls 引用 %compile_commands.json

如果没有 compile_commands.json 就直接写 .ccls

学习了!我问题也解决了!

ccls不需要包含源文件,估计是自动遍历搜寻所有源文件进来。

我对比了一下,把头部那句%compile_commands.json屏蔽掉之后,发现就很完美!

估计是ccls去找.json文件导致的问题

最后附上我的普遍实用性.ccls配置:

#%compile_commands.json
--target=arm-none-eabi
#%c -std=c11
-I/usr/include/newlib
-I./freertos/include/
-U__ICCARM__
-D__GNUC__
-U__clang__

越用越发现,emacs用得溜之后,比vscode好用很多

:sneezing_face: 我问题解决了,没有.json文件,我就屏蔽了那个玩意,突然就奏效。