如何为内核和设备 driver 开发设置 YouCompleteMe?

How to setup YouCompleteMe for kernel and device driver development?

我想为内核破解设置 vim,所以我安装了 YouCompleteMe 以自动完成。但是,无论我做什么,看起来我都无法正确配置它。它没有正确地完成语义;它只建议当前文件中已经使用的语义,甚至不包括 headers 或其他翻译单元中的语义,如果这不可能,那么 ycm 就没用了。有谁知道如何为特定目的做这件事?如果有必要包括我的 .vimrc.ycm_extra_conf.py 请在评论中询问。另外,如果我需要额外的工具,请指定它们,这样我也可以设置它们。

你想要cscope。有关设置说明,请参阅此处:

http://cscope.sourceforge.net/large_projects.html

内核非常庞大和复杂。 Cscope 在合理的时间内搜索它的性能非常好。

不过,这仍然是一个难题,因为内核大量使用 C 宏的方式对于工具来说并不总是很容易遵循。跟踪内核代码可能是一门艺术,需要练习。

这里有一些其他工具的更多提示:

http://kernelnewbies.org/FAQ/CodeBrowsing

以下是我使用 vim.

设置内核编程环境的方法

使用的工具:

  • OmniCompletion:vim 的集成功能(无需额外插件)用于自动完成
  • ctags:创建代码索引数据库,这是 OmniCompletion(和其他一些 vim 插件)所需要的
  • cscope:用于导航代码的工具(例如,您可以立即跳转到光标下的函数定义等)。创建它自己的代码索引数据库(不同于 ctags)。

1。安装工具

首先,安装vim、ctags和cscope:

$ sudo aptitude install vim vim-gtk cscope exuberant-ctags

2。创建索引数据库

现在创建 cscope 和 ctags 数据库。在你的内核源代码根目录 运行 下一个脚本(我使用 this tutorial 作为参考):

#!/bin/bash

list_sources() {
    echo "---> Listing sources..."

    find .                                   \
        -path "./arch*" -prune -o            \
        -path "./tmp*" -prune -o             \
        -path "./Documentation*" -prune -o   \
        -path "./scripts*" -prune -o         \
        -type f -name "*.[chsS]" -print >cscope.files

    find arch/arm/include/                   \
        arch/arm/kernel/                     \
        arch/arm/common/                     \
        arch/arm/boot/                       \
        arch/arm/lib/                        \
        arch/arm/mm/                         \
        arch/arm/mach-omap2/                 \
        arch/arm/plat-omap/                  \
        -type f -name "*.[chsS]" -print >>cscope.files
}

create_cscope_db() {
    echo "---> Creating cscope DB..."
    cscope -k -b -q
}

create_ctags_db() {
    echo "---> Creating CTags DB..."
    ctags -L cscope.files
}

cleanup() {
    echo "---> Removing garbage..."
    rm -f cscope.files
}

list_sources
create_cscope_db
create_ctags_db
cleanup

此脚本用于处理 ARM 体系结构代码(使用 OMAP 平台)。如果您需要使用其他架构(例如 x86),则需要适当更改脚本中的 find 行。

正如您从上面的脚本中看到的那样,接下来它会执行以下操作:

  1. 创建要索引的文件列表 (cscope.files),使用 find 命令。
  2. 为内核创建 cscope 数据库(默认使用 cscope.files 文件)(参见 man cscope 中的 -k 选项),使用下一个命令:

    $ cscope -b -q -k
    
  3. 创建 ctags 文件 (tags),使用 cscope.files 文件(参见 man ctags):

    $ ctags -L cscope.files
    
  4. 删除 cscope.files 文件,因为不再需要它。

3。为 cscope

配置 vim

下载 cscope_maps.vim file to your ~/.vim/plugin directory (see this link 了解详情)。

现在您可以使用 Ctrl+\, gCtrl+\, s 等内容在 vim 中导航您的内核代码。有关详细信息,请参阅 this。 vim 中的 :help cscope-find 命令也很有用。

4。为 OmniCompletion

配置 vim

要使用 OmniCompletion,您需要编辑 ~/.vimrc 文件。例如,这是我的 OmniCompletion 配置(将这些行添加到您的 ~/.vimrc):

"-------------------------------------------------------------------------------
" OmniCppCompletion plugin
"-------------------------------------------------------------------------------

" Enable OmniCompletion
" http://vim.wikia.com/wiki/Omni_completion
filetype plugin on
set omnifunc=syntaxcomplete#Complete

" Configure menu behavior
" http://vim.wikia.com/wiki/VimTip1386
set completeopt=longest,menuone
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
inoremap <expr> <C-n> pumvisible() ? '<C-n>' :
  \ '<C-n><C-r>=pumvisible() ? "\<lt>Down>" : ""<CR>'
inoremap <expr> <M-,> pumvisible() ? '<C-n>' :
  \ '<C-x><C-o><C-n><C-p><C-r>=pumvisible() ? "\<lt>Down>" : ""<CR>'

" Use Ctrl+Space for omni-completion
" 
inoremap <expr> <C-Space> pumvisible() \|\| &omnifunc == '' ?
  \ "\<lt>C-n>" :
  \ "\<lt>C-x>\<lt>C-o><c-r>=pumvisible() ?" .
  \ "\"\<lt>c-n>\<lt>c-p>\<lt>c-n>\" :" .
  \ "\" \<lt>bs>\<lt>C-n>\"\<CR>"
imap <C-@> <C-Space>

" Popup menu hightLight Group
highlight Pmenu ctermbg=13 guibg=LightGray
highlight PmenuSel ctermbg=7 guibg=DarkBlue guifg=White
highlight PmenuSbar ctermbg=7 guibg=DarkGray
highlight PmenuThumb guibg=Black

" enable global scope search
let OmniCpp_GlobalScopeSearch = 1
" show function parameters
let OmniCpp_ShowPrototypeInAbbr = 1
" show access information in pop-up menu
let OmniCpp_ShowAccess = 1
" auto complete after '.'
let OmniCpp_MayCompleteDot = 1
" auto complete after '->'
let OmniCpp_MayCompleteArrow = 1
" auto complete after '::'
let OmniCpp_MayCompleteScope = 0
" don't select first item in pop-up menu
let OmniCpp_SelectFirstItem = 0

OmniCompletion 将使用您的 ctags 文件 (tags)。您现在可以使用 Ctrl+Space(由上面的 vim 配置添加)来使用补全。

5。一些额外的东西

另请查看下一个插件:

请原谅我将这个死去已久的 post 从永恒的安息中唤醒,但我一直在与同样的问题作斗争,而接受的答案并没有回答这个问题。 问题是使用 YouCompleteMe 插件 为内核和设备 driver 开发设置 Vim。虽然接受的答案很有帮助,但它让我走上了错误的道路,因为我想让 YouCompleteMe 工作。

我就是这样解决的

我将在下面概述我是如何解决它的,以防其他人遇到这个问题,希望它能帮助他们。我不是任何这些技术的专家,所以它可能不是最好的方法,但我没能找到解决问题的任何其他方法。

工具

  1. 安装Vim
  2. 安装YouCompleteMe
  3. 安装BEAR

密码

我跟进了 Linux Device Drivers, Third Edition 并且我相信许多在这个问题上跌跌撞撞的人可能会尝试同样的事情。 在第 2 章中,作者为设备 driver 展示了一个简单的 "Hello, world!",我将其复制如下:

// hello.c
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void){
    printk(KERN_ALERT "Hello, world\n");
    return 0;
}

static void hello_exit(void){
    printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

问题

在 Vim 中打开它可能会让 YCM 抱怨 #include <linux/init.h>

得到linuxheaders

显然,内核编译比一般 gcc hello.c 难一些,您需要在计算机上安装 linux header 文件。我使用 arch(顺便说一句),所以我使用 pacman -S linux-headers 获取它们,但其他发行版应该有类似的方法来使用包管理器获取它们。如果一切都失败了,您可以下载 Linux 内核源代码,包括来自 Website 的 header 文件。 如果您使用包管理器安装,您的 /lib/modules/$(uname -r)/build/include 目录中应该有 headers。如果您已经安装了内核源代码,header 位于 /path/to/source/include/.

获取 Makefile

此外,您需要一个 Makefile,它可以将您的 hello.c 和 link 所有依赖项一起构建。为此,我使用了 the Makefile for the book。 但是请注意,此 Makefile 指向 /lib/modules/$(uname -r)/build,因此如果您使用内核源代码进行构建,则必须更改它。 此外,Makefile 将尝试构建一堆其他示例,因此您可以删除它们。 obj-m := hello.o 应该是此示例的全部内容。

测试生成文件

如果此时你 运行 make,它应该编译并且你可以 insmod 和 rmmod 新创建的 hello.ko 模块。然而你的Vim还是会抱怨。

创建编译数据库

除此之外,首先 运行 make clean 因为 BEAR demands a clean directory. Then run bear make and it should generate a 'compile_commands.json' for you. This is what the YCM guide was referring to here.

终点线

现在,如果您在 vim 中重新打开 hello.c,它应该不会再抱怨 init.h,并且一切都应该按预期工作。 你可能 运行 进入 this issue 尽管我已经通过将以下内容添加到我的 .vimrc 文件中解决了一堆 YCM 投诉:

let g:ycm_filter_diagnostics = {                                      
  \ "c": {                                                            
  \   "regex": [                                                      
  \     "-mno-fp-ret-in-387",                                         
  \     "-mpreferred-stack-boundary=3",                               
  \     "-mskip-rax-setup",                                           
  \     "-mindirect-branch=thunk-extern",                             
  \     "-mindirect-branch-register",                                 
  \     "-fno-allow-store-data-races",                                
  \     "-fplugin-arg-structleak_plugin-byref-all",                   
  \     "-fno-var-tracking-assignments",                              
  \     "-fconserve-stack",                                           
  \     "-mrecord-mcount"                                             
  \   ]                                                               
  \ }                                                                 
  \}       

需要比我更有资格的人来解释为什么必须过滤掉这些。我对上面 link 编辑的 github 问题中的解释感到满意。 但是无论如何,现在 Vim 中您应该不会再收到错误或警告了,因为 YouCompleteMe 为内核和设备 driver 开发提供了全方位的服务。

我希望这个答案能找到并帮助仍在为这个问题苦苦挣扎的任何人!