Search code examples
cvimlinux-kernelvim-plugin

How to setup YouCompleteMe for kernel and device driver development?


I would like to setup vim for kernel hacking so I have installed YouCompleteMe for auto completion. However, no matter what I do It looks like I can't configure it properly. It does not do semantic completion properly; It only suggests the semantics already used in the current file not even the ones in the headers or other translation units and if that's impossible then ycm is pretty useless. Does anyone know how to do it for the particular purpose? If it's necessary to include my .vimrc or .ycm_extra_conf.py please ask in the comments. Also if I need extra tools please specify them so I can set them up as well.


Solution

  • Here is how I setup my kernel programming environment with vim.

    Tools used:

    • OmniCompletion: integrated feature of vim (no extra plugins required) for auto-completion
    • ctags: creates code index database, which is needed for OmniCompletion (and some other vim plugins)
    • cscope: tool for navigating the code (e.g. you can immediately jump to the function definition under cursor, etc.). Creates it's own code index database (different than ctags).

    1. Install tools

    First, install vim, ctags and cscope:

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

    2. Create index database

    Now create cscope and ctags databases. In your kernel sources root directory run next script (I used this tutorial as reference):

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

    This script intended for working with ARM architecture code (with OMAP platform). If you need to work with another architecture (e.g. with x86), you need to change find lines in script appropriately.

    As you can see from script above, it does next:

    1. Create list of files to be indexed (cscope.files), using find command.
    2. Create cscope database (using cscope.files file by default) for kernel (see -k option in man cscope), using next command:

      $ cscope -b -q -k
      
    3. Create ctags file (tags), using cscope.files file (see man ctags):

      $ ctags -L cscope.files
      
    4. Remove cscope.files file, as it's not needed anymore.

    3. Configure vim for cscope

    Download cscope_maps.vim file to your ~/.vim/plugin directory (see this link for details).

    Now you can navigate your kernel code in vim using stuff like Ctrl+\, g, Ctrl+\, s, etc. See this for details. Also :help cscope-find command in vim can be helpful.

    4. Configure vim for OmniCompletion

    To use OmniCompletion you will need to edit your ~/.vimrc file. For example here is my OmniCompletion configuration (add these lines to your ~/.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 will use your ctags file (tags). You can use completion now using Ctrl+Space (added by vim config above).

    5. Some extra stuff

    Check out also next plugins: