开发环境:
- Ubuntu22.04 LTS
- x86_64架构Intel CPU
YCM(YouCompleteMe)是一款用于vim编辑器的强大代码补全插件。
YCM提供许多强大功能:
- 代码补全;
- 语法错误、语义错误检查;
- 语义代码高亮;
- 函数、变量定义跳转;
- 函数参数列表和返回类型提示;
- 函数文档显示;
- …
问题描述
如果您开启了YCM的语法检查功能,当您在编写c++代码时,YCM可能无法找相应的c++头文件。比如:
#include <iostream>
语句可能会出现iostream not found
的错误。
然而这并不意味着您不能顺利编译并运行该c++源文件。
问题分析
YCM使用libclang或者clangd作为检查代码错误和进行代码补全的引擎。检查代码错误时实际上就是使用libclang或者clangd将代码编译一遍,并且给出错误信息。
因此,如果没有在libclang或者clangd的编译选项中正确指出c++头文件路径,就会在编写c++源代码时出现头文件找不到的情况。
解决方法
Step1.
YCM通过.ycm_extra_conf.py
指定libclang或者clangd的编译选项,所以只要在该python文件中为它们指定正确的选项就可以了。这样,libclang或者clangd就知道去哪里找c++头文件了。
建议将.ycm_extra_conf.py
放在用户主目录。因为YCM首先会在源文件目录下查找.ycm_extra_conf.py
,如果没找到就会递归地去上层目录中寻找。
YouCompleteMe
提供了.ycm_extra_conf.py
的一个示例模板,在我的环境中,该模板位于~/.vim/plugged/YouCompleteMe/third_party/ycmd
目录下。
将该模板复制到主目录~
。
Ok,接下来的工作就很简单了。😃
Step2.
我们需要更改~/.ycm_extra_conf.py
文件中的flags列表,该列表存储要传递给clangd或者libclang的参数。
-
将列表中的所有
'-isystem'
及后面紧跟着的参数删除。 -
随便写一段c++代码,比如
test.cpp
,用g++ -v test.cpp
编译。-v
选项会显示编译的详细信息。
从这些信息中我们可以提取到以下几行:#include “…” search starts here:
#include <…> search starts here:
/usr/include/c++/11
/usr/include/x86_64-linux-gnu/c++/11
/usr/include/c++/11/backward
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include这些信息显示了c++头文件的搜素路径,把它们添加到
~/.ycm_extra_conf.py
的flags列表中,添加后列表内容大致如下:flags = [ '-Wall', '-Wextra', #'-Werror', #'-Wc++98-compat', '-Wno-long-long', '-Wno-variadic-macros', '-fexceptions', '-stdlib=libc++', # THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which # language to use when compiling headers. So it will guess. Badly. So C++ # headers will be compiled as C headers. You don't want that so ALWAYS specify # a "-std=<something>". # For a C project, you would set this to something like 'c99' instead of # 'c++11'. '-std=c++11', # ...and the same thing goes for the magic -x option which specifies the # language that the files to be compiled are written in. This is mostly # relevant for c++ headers. # For a C project, you would set this to 'c' instead of 'c++'. '-x', 'c++', '-I', '.', '-isystem', '/usr/include/c++/11', '-isystem', '/usr/include/x86_64-linux-gnu/c++/11', '-isystem', '/usr/include/c++/11/backward', '-isystem', '/usr/lib/gcc/x86_64-linux-gnu/11/include', '-isystem', '/usr/local/include', '-isystem', '/usr/include/x86_64-linux-gnu', '-isystem', '/usr/include', ]
注意最后几行的
'-isystem'
内容,这些都是根据g++ -v
的输出所添加的头文件搜索路径。保存退出。
Ok,大功告成。现在重新启动vim编写c++源文件,就不会出现头文件找不到的错误了。😉
vim下方会出现是否使用我们刚才修改过的配置文件的提示:
选择Ok即可。这个提示每次启动vim时都会出现,您可以通过在.vimrc中加入let g:ycm_confirm_extra_conf = 0
来禁用这个提示。
最终效果如下:
YCM没有报错。
总结
之所以会出现头文件找不到的错误,就是因为clangd不知道要去哪里找c++头文件。既然这样,我们便在.ycm_extra_config.py
中告诉它。
YCM本身非常强大,更多信息和使用技巧请参考YCM的github主页:https://github.com/ycm-core/YouCompleteMe。
Enjoy yourself. 😃