如何为内核和设备驱动程序开发设置YouCompleteMe?

时间:2015-05-12 01:05:26

标签: c vim linux-kernel vim-plugin

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

3 个答案:

答案 0 :(得分:4)

请原谅我从永恒的休息中唤醒了这个漫长的死亡帖子,但是我一直在与这个问题作斗争,而公认的答案并不能回答这个问题。 问题是使用 YouCompleteMe插件设置Vim以进行内核和设备驱动程序开发。尽管接受的答案是有帮助的,但它使我走上了一条错误的道路,因为我想让YouCompleteMe正常工作。

这就是我解决的方式

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

工具

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

代码

我一直跟随Linux Device Drivers, Third Edition,毫无疑问,许多在这个问题上绊脚石的人可能会尝试相同的方法。 在第二章中,作者展示了一个简单的“世界,你好!”设备驱动程序,我将在下面复制:

// 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>

获取linux标头

显然,内核编译比您的平均gcc hello.c要难一些,并且您需要在计算机上安装linux头文件。我使用arch(btw),所以我使用pacman -S linux-headers来获得它们,但是其他发行版应该也具有使用包管理器来获得它们的类似方法。如果所有其他方法均失败,则可以下载Linux内核源代码,包括来自其Website的头文件。 如果使用程序包管理器进行安装,则标头应位于/lib/modules/$(uname -r)/build/include目录中。如果您已安装内核源代码,则标头位于/path/to/source/include/中。

获取Makefile

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

测试Makefile

如果此时运行make,它将编译并可以对新创建的hello.ko模块进行insmod和rmmod。但是您的Vim仍然会抱怨。

创建编译数据库

要使其消失,请先运行make clean,因为BEAR demands a clean directory。然后运行bear make,它将为您生成一个'compile_commands.json'。这就是YCM指南所指的here

终点线

现在,如果您在vim中重新打开hello.c,它就不会再抱怨init.h了,一切都会按预期进行。 您可能会遇到this issue,但由于一堆YCM投诉,我已通过在.vimrc文件中添加以下内容解决了该问题:

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"                                             
  \   ]                                                               
  \ }                                                                 
  \}       

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

我希望这个答案能找到并帮助仍然在这个问题上挣扎的人!

答案 1 :(得分:3)

以下是我使用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. 使用tags文件创建ctags文件(cscope.files)(参见man ctags):

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

  5. 3。为cscope配置vim

    cscope_maps.vim文件下载到~/.vim/plugin目录(有关详细信息,请参阅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
    " http://stackoverflow.com/questions/510503/ctrlspace-for-omni-and-keyword-completion-in-vim
    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。一些额外的东西

    查看下一个插件:

答案 2 :(得分:1)

你想要cscope。请参阅此处获取设置说明:

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

内核非常庞大而且复杂。 Cscope在合理的时间内搜索它的效果非常好。

但是,这仍然是一个难题,因为内核大量使用C宏,这种方式对于工具而言并不容易。跟踪内核代码可能有点艺术,需要练习。

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

http://kernelnewbies.org/FAQ/CodeBrowsing