¿Cómo funciona realmente kbuild?
linux makefile (1)
Los Makefiles de Kbuild no son los más fáciles de leer, pero aquí hay un desenredo de alto nivel (usando el kernel 4.0-rc3):
El Makefile de nivel superior hace
include $(srctree)/scripts/Kbuild.include
, donde
$(srctree)
es el directorio del kernel de nivel superior.Kbuild.include
define varias cosas comunes y ayudantes. Entre estos se encuentra labuild
:### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: # $(Q)$(MAKE) $(build)=dir build := -f $(srctree)/scripts/Makefile.build obj
build
se usa con un comando como$(MAKE) $(build)=dir
para realizar la compilación del directoriodir
. Hace uso descripts/Makefile.build
.Volviendo al Makefile de nivel superior, hay lo siguiente:
$(vmlinux-dirs): prepare scripts $(Q)$(MAKE) $(build)=$@
vmlinux-dirs
contiene una lista de subdirectorios para compilar ( init , usr , kernel , etc.).$(Q)$(MAKE) $(build)=<subdirectory>
se ejecutará para cada subdirectorio.La regla anterior compila archivos de objetos tanto para la imagen del kernel como para los módulos. Más abajo en el Makefile de nivel superior, hay algunas cosas adicionales específicas del módulo:
ifdef CONFIG_MODULES ... modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin # Do additional module-specific stuff using # scripts/Makefile.modpost among other things # (my comment). ... ... endif # CONFIG_MODULES
Buscando en
scripts/Makefile.build
(el Makefile usado por$(build)
) ahora, comienza por inicializar las listasobj-*
y varias otras listas:# Init all relevant variables used in kbuild files so # 1) they have correct type # 2) they do not inherit any value from the environment obj-y := obj-m := lib-y := lib-m :=
Un poco más abajo, se carga en el archivo Kbuild donde se establecen
obj-y
,obj-m
, etc.include $(kbuild-file)
Más abajo está la regla predeterminada, que tiene las listas
$(obj-y)
y$(obj-m)
como requisitos previos:__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) / $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) / $(subdir-ym) $(always) @:
Los requisitos previos de
$(obj-y)
provienen de$(builtin-target)
, que se define de la siguiente manera:builtin-target := $(obj)/built-in.o ... $(builtin-target): $(obj-y) FORCE $(call if_changed,link_o_target)
El edificio real parece ser realizado por la siguiente regla:
# Built-in and composite module parts $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c)
if_changed_rule
es deKbuild.include
. La regla termina ejecutando los siguientes comandos enMakefile.build
:define rule_cc_o_c $(call echo-cmd,checksrc) $(cmd_checksrc) / $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); / ... endef
$(cmd_cc_o_c)
parece ser el comando de compilación real. La definición habitual (hay dos posibilidades enMakefile.build
, AFAICS) parece ser la siguiente:cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
A menos que se establezca explícitamente utilizando, por ejemplo,
make CC=clang
,CC
defecto engcc
, como se puede ver aquí en el Makefile de nivel superior:ifneq ($(CC),) ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) COMPILER := clang else COMPILER := gcc endif export COMPILER endif
La forma en que lo desenredé fue haciendo una CTRL-C durante una compilación del kernel y viendo dónde cometió el error. Otra técnica práctica de make
depuración es usar $(warning $(variable))
para imprimir el valor de la variable
.
Cuando estoy desarrollando un controlador de linux, he leído acerca de cómo escribir linux kbuild makefile a través de este document
Sé que el sistema kbuild usa variables makefile como obj-y obj-m para determinar qué construir y cómo construir.
Pero lo que me confunde es dónde el sistema kbuild realmente ejecuta el proceso de compilación. En una palabra, si tengo obj-m = ao
, entonces ¿dónde el sistema kbuild analiza obj-m
y ejecuta gcc ac
?