Configuración de Vim para el desarrollo del kernel de Linux
linux-kernel (1)
Las principales diferencias entre el kernel de Linux y el proyecto C regular (desde el punto de vista del desarrollador) son las siguientes:
- El kernel es un proyecto muy grande (por lo que debe elegir qué código indexar)
- tiene un código dependiente de la arquitectura (y solo está interesado en una arquitectura específica a la vez; otras arquitecturas no deben estar indexadas)
- tiene un estilo de codificación muy específico al que debe atenerse (y vim debe configurarse para mostrar el código en consecuencia)
- no utiliza la biblioteca estándar de C, sino que tiene sus propias rutinas similares (por lo que su herramienta de índice no debe indexar los encabezados de libc)
Instalando herramientas de indexación
Para navegar por el código del kernel recomendaría herramientas de cscope
y ctags
. Para instalarlos ejecute el siguiente comando:
$ sudo aptitude install cscope exuberant-ctags
Una pequeña explicación:
-
cscope
: se utilizará para navegar por el código (cambiar entre funciones, etc.) -
ctags
: es necesario para el complementoTagbar
(seTagbar
más adelante) y para laOmni completion
(mecanismo de finalización automática en vim); También se puede utilizar para la navegación.
Creación de base de datos de índice
Ahora deberías indexar los archivos fuente de tu kernel. Aquí hay 2 enfoques: crear índice manualmente o usar el script disponible en el kernel. Si no está seguro de cuál es la mejor manera para usted, le recomiendo ir con el script del kernel, ya que hace muchos trucos ingeniosos detrás de la escena (como ignorar las fuentes no construidas y mover los archivos de encabezado sobre la lista de resultados).
Pero antes que nada, configure y genere el kernel para su arquitectura / placa, ya que los archivos creados se pueden usar más adelante para mejorar el proceso de indexación.
Indexación con scripts/tags.sh
Kernel tiene una secuencia de scripts/tags.sh
bastante buena ( scripts/tags.sh
) para crear la base de datos de índices del kernel. Uno debe usar make cscope
y make tags
para crear un índice, en lugar de ejecutar ese script directamente.
Ejemplo:
$ make O=. ARCH=arm SUBARCH=omap2 COMPILED_SOURCE=1 cscope tags
dónde
-
O=.
- use rutas absolutas (útil si desea cargar archivos de índice de cscope / ctags creados fuera del directorio del kernel, por ejemplo, para el desarrollo de módulos de kernel fuera del árbol). Si desea usar rutas relativas (es decir, solo va a realizar el desarrollo en el directorio del kernel), simplemente omita ese parámetro -
ARCH=...
- selecciona la arquitectura de la CPU para ser indexada. Ver directorios enarch/
para referencia. Por ejemplo, siARCH=arm
, el directorioarch/arm/
se indexará, el resto de los directoriosarch/*
se ignorarán -
SUBARCH=...
- seleccione la sub-arquitectura (es decir, los archivos relacionados con el tablero) para ser indexados. Por ejemplo, siSUBARCH=omap2
, solo seSUBARCH=omap2
arch/arm/mach-omap2/
yarch/arm/plat-omap/
, el resto de máquinas y plataformas se ignorarán. -
COMPILED_SOURCE=1
- indexar solo archivos compilados. Por lo general, solo está interesado en los archivos de origen utilizados en su compilación (por lo tanto, compilados). Si desea indexar también los archivos que no se crearon, simplemente omita esta opción. -
cscope
- regla para hacer el índice de cscope -
tags
- regla para hacer ctags index
Indexación manual
Es posible que la secuencia de comandos del kernel ( tags.sh
) no funcione correctamente o que desee tener más control sobre el proceso de indexación. En esos casos, debe indexar las fuentes del kernel manualmente.
Las reflexiones sobre la indexación manual se tomaron de here .
Primero debe crear el archivo cscope.files
que cscope.files
todos los archivos que desea indexar. Por ejemplo, estoy usando los siguientes comandos para enumerar archivos para la arquitectura ARM ( arch/arm
), y particularmente para la plataforma OMAP (excluyendo el resto de plataformas para facilitar la navegación):
find $dir /
-path "$dir/arch*" -prune -o /
-path "$dir/tmp*" -prune -o /
-path "$dir/Documentation*" -prune -o /
-path "$dir/scripts*" -prune -o /
-path "$dir/tools*" -prune -o /
-path "$dir/include/config*" -prune -o /
-path "$dir/usr/include*" -prune -o /
-type f /
-not -name ''*.mod.c'' /
-name "*.[chsS]" -print > cscope.files
find $dir/arch/arm /
-path "$dir/arch/arm/mach-*" -prune -o /
-path "$dir/arch/arm/plat-*" -prune -o /
-path "$dir/arch/arm/configs" -prune -o /
-path "$dir/arch/arm/kvm" -prune -o /
-path "$dir/arch/arm/xen" -prune -o /
-type f /
-not -name ''*.mod.c'' /
-name "*.[chsS]" -print >> cscope.files
find $dir/arch/arm/mach-omap2/ /
$dir/arch/arm/plat-omap/ /
-type f /
-not -name ''*.mod.c'' /
-name "*.[chsS]" -print >> cscope.files
Para la arquitectura x86 ( arch/x86
) puedes usar algo como esto:
find $dir /
-path "$dir/arch*" -prune -o /
-path "$dir/tmp*" -prune -o /
-path "$dir/Documentation*" -prune -o /
-path "$dir/scripts*" -prune -o /
-path "$dir/tools*" -prune -o /
-path "$dir/include/config*" -prune -o /
-path "$dir/usr/include*" -prune -o /
-type f /
-not -name ''*.mod.c'' /
-name "*.[chsS]" -print > cscope.files
find $dir/arch/x86 /
-path "$dir/arch/x86/configs" -prune -o /
-path "$dir/arch/x86/kvm" -prune -o /
-path "$dir/arch/x86/lguest" -prune -o /
-path "$dir/arch/x86/xen" -prune -o /
-type f /
-not -name ''*.mod.c'' /
-name "*.[chsS]" -print >> cscope.files
Donde dir
variable puede tener uno de los siguientes valores:
-
.
: si va a trabajar solo en el directorio de código fuente del kernel; en este caso, esos comandos deben ejecutarse desde el directorio raíz del código fuente del kernel - ruta absoluta al directorio de código fuente de su kernel : si va a desarrollar algún módulo de kernel fuera de árbol; En este caso, el script puede ejecutarse desde cualquier lugar.
Estoy usando la primera opción ( dir=.
), Porque no estoy desarrollando ningún módulo fuera de árbol.
Ahora, cuando el archivo cscope.files
está listo, necesitamos ejecutar la indexación real:
$ cscope -b -q -k
Donde el parámetro -k
le dice a cscope
que no indexe la biblioteca estándar de C (ya que el kernel no la usa).
Ahora es el momento de crear la ctags
de datos del índice ctags
. Para acelerar esta etapa, vamos a reutilizar el ya creado cscope.files
:
$ ctags -L cscope.files
De acuerdo, las bases de datos de índice de cscope
y ctags
están creadas, y puede eliminar el archivo cscope.files
, ya que no lo necesitamos más:
$ rm -f cscope.files
Los siguientes archivos contienen bases de datos de índice (para cscope
y ctags
):
- cscope.in.out
- cscope.out
- cscope.po.out
- tags
Manténgalos en la raíz del directorio de fuentes del kernel.
plugins vim
NOTA : Además, muestro cómo usar el agente patógeno para manejar los complementos Vim. Pero ahora que se lanzó Vim 8, se puede usar la carga de paquetes nativos para el mismo propósito.
A continuación vamos a instalar algunos complementos para vim. Para comprenderlo mejor, te animo a que uses el complemento de patógenos . Le permite simplemente git clone
complementos de vim a su ~/.vim/bundle/
y mantenerlos aislados, en lugar de mezclar archivos de diferentes complementos en el directorio ~/.vim
.
Instale el patógeno como se describe here .
No te olvides de hacer las siguientes cosas (como se describe en el mismo enlace):
Agrega esto a tu
vimrc
:
execute pathogen#infect()
Si eres nuevo en Vim y te falta
vimrc
,vim ~/.vimrc
y pega el siguiente ejemplo súper mínimo:
execute pathogen#infect() syntax on filetype plugin indent on
Instalando mapas cscope para vim
Vim ya tiene soporte para cscope (ver :help cscope
). Puedes saltar a un símbolo o archivo usando comandos como :cs fg kfree
. Aunque no es tan conveniente. Para acelerar las cosas, puede utilizar los accesos directos en su lugar (para que pueda poner el cursor en alguna función, presionar una combinación de teclas y saltar a la función). Para agregar accesos directos a cscope, debe obtener el archivo cscope_maps.vim
.
Para instalarlo usando un patógeno , simplemente puede clonar this repositorio a su ~/.vim/bundle
:
$ git clone https://github.com/joe-skb7/cscope-maps.git ~/.vim/bundle/cscope-maps
Ahora deberías poder navegar entre funciones y archivos en vim usando atajos. Abra algún archivo fuente del kernel, ponga el cursor del teclado en alguna llamada de función y presione Ctrl + / seguido de g . Debería llevarte a la implementación de la función. O puede mostrarle todas las implementaciones de funciones disponibles, luego puede elegir cuál usar: .
Para el resto de asignaciones de claves, consulte el archivo cscope_maps.vim .
También puedes usar comandos en vim como:
:cs f g kmalloc
Ver :help cscope
para más detalles.
nota de ctags
ctags aún puede ser útil para la navegación, por ejemplo cuando se busca alguna declaración #define
. Puede poner el cursor en este uso de definición y presionar g seguido de Ctrl + ] . Vea esta respuesta para más detalles.
nota cscope
El siguiente truco se puede usar para encontrar la declaración de estructura en el kernel:
:cs f t struct device {
Tenga en cuenta que el comando anterior se basa en el estilo específico de declaración de estructura (utilizado en el kernel), por lo que sabemos que la declaración de estructura siempre tiene esta forma: struct some_stuct {
. Este truco podría no funcionar en proyectos con otro estilo de codificación.
nota de desarrollo de módulos fuera de árbol
Si está desarrollando un módulo fuera de árbol, probablemente deba cargar las bases de datos cscope
y ctags
desde el directorio del kernel. Se puede hacer con los siguientes comandos en vim (en modo de comando).
Cargar la base de datos cscope externa:
:cs add /path/to/your/kernel/cscope.out
Cargar base de datos ctags externa:
:set tags=/path/to/your/kernel/tags
vimrc
~/.vimrc
deben hacer algunas modificaciones a su ~/.vimrc
, para apoyar mejor el desarrollo del kernel.
En primer lugar, resalte la columna 81 con una línea vertical (ya que la codificación del kernel requiere que mantenga la longitud de sus líneas a un máximo de 80 caracteres):
" 80 characters line
set colorcolumn=81
"execute "set colorcolumn=" . join(range(81,335), '','')
highlight ColorColumn ctermbg=Black ctermfg=DarkRed
Anule el comentario de la segunda línea si también desea resaltar más de 80 columnas.
Los espacios finales están prohibidos por el estilo de codificación del kernel, por lo que es posible que desee resaltarlos:
" Highlight trailing spaces
" http://vim.wikia.com/wiki/Highlight_unwanted_spaces
highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace //s/+$/
autocmd BufWinEnter * match ExtraWhitespace //s/+$/
autocmd InsertEnter * match ExtraWhitespace //s/+/%#/@<!$/
autocmd InsertLeave * match ExtraWhitespace //s/+$/
autocmd BufWinLeave * call clearmatches()
Estilo de codificación del kernel
Para que vim respete el estilo de codificación del kernel, puede utilizar el complemento listo para usar: vim-linux-coding-style .
Complementos útiles
Los complementos siguientes se usan comúnmente, por lo que también puede encontrarlos útiles:
También se trata de complementos interesantes, pero es posible que deba configurarlos para el kernel:
Omni finalización
Vim 7 (y superior) ya tiene incorporado el soporte de finalización automática. Se llama Omni completion
. Ver : ayuda a la nueva omisión de terminación para más detalles.
La finalización de Omni funciona bastante lento en un proyecto tan grande como el kernel. Si aún lo desea, puede habilitarlo agregando las siguientes líneas a su ~/.vimrc
:
" 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
" https://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
Y usa Ctrl + Espacio para completar automáticamente.
Apariencia de ojos dulces
256 colores
En primer lugar, debe asegurarse de que su terminal admita 256 colores. Por ejemplo, se puede lograr utilizando el terminal urxvt-256 . Para gnome-terminal
, simplemente puede agregar la siguiente línea a su ~/.bashrc
:
export TERM="xterm-256color"
Una vez hecho esto, coloque la siguiente línea en su ~/.vimrc
:
set t_Co=256
Esquema de colores
Ahora descargue los esquemas que prefiera ~/.vim/colors
y selecciónelos en ~/.vimrc
:
set background=dark
colorscheme hybrid
Qué combinación de colores usar es una materia fuertemente basada en la opinión. Puedo recomendar mrkn256 , hybrid y solarized para empezar.
Fuente
Hay muchas buenas fuentes para programar por ahí. Muchos programadores en Linux usan la fuente Terminus , puedes probarla para empezar.
Deficiencias conocidas
Algunas características todavía faltan en vim.
- cscope / ctags no puede usar las definiciones de
include/generated/autoconf.h
e ignorar el código que no fue creado. Todavía puede ser útil tener todo el código indexado para usarlo como referencia cuando se codifica. - No hay expansión de macros (bueno, hay alguna function ahí fuera (basada en
gcc -E
), pero no estoy seguro de si funcionará para el núcleo).
El único IDE que conozco para manejar esos problemas es Eclipse con CDT .
El desarrollo del kernel es realmente diferente del desarrollo de un proyecto de C tradicional (desde mi punto de vista, como novato). Por lo tanto, siempre me pregunto cuál es la configuración vim de un hacker del kernel.
Lo más importante es que la forma de navegar por el árbol fuente del kernel en vim .. Intenté ctags
, sin embargo, funciona terriblemente.
¿Alguien me puede dar una pista?