Análisis del Makefile del kernel de Linux 2.6

1. Información general

Makefile consta de cinco partes:

  • Makefile: El directorio raíz Makefile, que lee el archivo .config y es responsable de crear vmlinux (imagen del kernel) y módulos (archivos de módulo).
  • .config: Archivo de configuración del kernel (generalmente generado por make menuconfig).
  • arch/$(ARCH)/Makefile: Makefile del procesador de destino.
  • scripts/Makefile.*: Todas las reglas de kbuild Makefile, incluyen definiciones / reglas, etc.
  • kbuild Makefiles: Cada subdirectorio tiene kbuild Makefiles, que son responsables de generar destinos integrados o modulares. (Nota: kbuild Makefile se refiere al Makefile que usa la estructura kbuild, y la mayoría de los Makefiles del kernel son kbuild Makefiles).

2. archivo kbuild

2.1. obj-y和obj-m

El Makefile de kbuild más simple solo puede contener:

obj-$(CONFIG_FOO) += foo.o

Que $(CONFIG_FOO)puede ser igual ayom, y su valor viene dado por el archivo .config. Si no $(CONFIG_FOO)es ni y ni m, el archivo no se compilará ni vinculará

Cuando es $(CONFIG_FOO)igual ay, la declaración anterior es equivalente a obj-y + = foo.o, le dice a kbuild que hay un archivo objeto llamado foo.o en el directorio actual, que se compilará a partir de foo.c o foo.S .

Cuando $(CONFIG_FOO)es igual am, significa que foo.o debe compilarse en un módulo.

2.1.1. obj-y 生成 incorporado. o

Kbuild compila todos los $(obj-y)archivos y llama "$(LD) -r"a fusionar todos estos archivos en built-in.oarchivos. Este archivo incorporado. O será utilizado por el Makefile en el directorio de nivel superior y finalmente vinculado a vmlinux.

2.1.2. El destino se compila a partir de varios archivos fuente.

Si un destino se compila a partir de varios archivos fuente, puede $(<module_name>-objs)decirle a kbuild estos archivos fuente a través de o $ (<module_name> -y). Kbuild puede reconocer los sufijos -objs y -y, por ejemplo:

#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

Kbuild compilará todos $(isdn-objs)los objetos que contiene y los llamará "$(LD) -r"para vincularlos al archivo isdn.o.

El siguiente es un ejemplo del uso del sufijo -y. La ventaja del sufijo -y es que puede usar CONFIG_XXXsímbolos para decidir si agregar algunos archivos fuente (.o se compila a partir del .c o .S correspondiente):

#fs/ext2/Makefile
obj-$(CONFIG_EXT2_FS)        += ext2.o
ext2-y                       := balloc.o bitmap.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

2.1.3. Llamar al subdirectorio Makefile

Makefile solo es responsable de compilar objetos en el directorio actual. Los objetos en subdirectorios están a cargo de Makefiles en subdirectorios. ¿Cómo hacer una llamada al Makefile en el subdirectorio? La respuesta es incluir los subdirectorios en obj-y u obj-m. P.ej:

#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/

Cuando CONFIG_EXT2_FS es yo m, el sistema kbuild llamará al comando make en el directorio ext2 (es decir, llamará al Makefile en el directorio ext2)

2.2. lib-y 和 lib-m

En un directorio, obj-ylos archivos enumerados se compilarán en built-in.oarchivos y lib-y或lib-mlos archivos enumerados se generarán en el directorio actual lib.a.

注意:一般lib-y或lib-m只用在lib/和arch/*/lib这两个目录中。

2.3. Variables de opciones del compilador

2.3.1. ccflags-y、asflags-y、ldflags-y

Estas tres variables solo son válidas en el Makefile actual. Suplemento: Es $(KBUILD_CFLAGS)una variable definida en el directorio raíz Makefile, que se aplica a todo el número de núcleos.

2.3.2. subdirectorio-ccflags-y 、 subdirectorio-asflags-y

Estas dos variables actúan sobre el Makefile actual y todos sus subdirectorios.

2.3.3. CFLAGS _ $ @ 、 AFLAGS _ $ @

Estas dos variables solo son válidas en el Makefile actual. $ @ se puede usar para especificar el nombre del archivo, de modo que diferentes archivos puedan usar diferentes opciones de compilación. P.ej:

# drivers/scsi/Makefile
CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ /
                     -DGDTH_STATISTICS
CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

2.4. $ (src) 、 $ (obj) 、 $ (kecho)

$(src)Señale la ruta relativa del directorio actual de Makefie. $(obj)Señale el directorio relativo utilizado para guardar el archivo de destino. Los ejemplos son los siguientes:

#drivers/scsi/Makefile
$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
       $(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl

Aquí, $(src)es igual a drivers / scsi /, y $(obj)también es igual a drivers / scsi /.

Cuando se usa el “make -s”comando, solo se emiten mensajes de advertencia y error. $(kecho)El siguiente contenido se puede enviar al flujo de salida estándar (generalmente la pantalla), siempre que no se utilice "make -s". Los ejemplos son los siguientes:

#arch/blackfin/boot/Makefile
$(obj)/vmImage: $(obj)/vmlinux.gz
       $(call if_changed,uimage)
       @$(kecho) 'Kernel: $@ is ready'

2.5. $ (CC) funciones relacionadas

2.5.1. como opción 、 opción ld 、 opción cc

Al compilar y vincular archivos, se puede usar xx-opiton para verificar $(CC)si las opciones de compilación utilizadas actualmente son compatibles. Si no se admite el primero, se puede utilizar el segundo. P.ej:

#arch/sh/Makefile
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)

Si el actual $(CC)no es compatible -Wa$(comma)-isa=$(isa-y), puede usar la segunda opción de compilación (vacía aquí).

2.5.2. cc-opción-en

cc-option-yn se usa para verificar $(CC)si la opción del compilador dada es compatible. Si es compatible, devuelve y; de lo contrario, devuelve n. P.ej:

#arch/ppc/Makefile
biarch := $(call cc-option-yn, -m32)
aflags-$(biarch) += -a32
cflags-$(biarch) += -m32

2.5.3. cc-option-align

Después de 3.0, gcc cambió los tipos de opciones de alineación, como funciones y bucles específicos. Cuando gcc <3.00, cc-option-align = -malign; cuando gcc> = 3.00, cc-option-align = -falign. Utilice $ (cc-option-align) para seleccionar el prefijo correcto. P.ej:

KBUILD_CFLAGS += $(cc-option-align)-functions=4

2.5.4. cc-versión 、 cc-ifversion 、 cc-versión completa

cc-version devuelve la $(CC)versión. Si $(CC)es gcc 3.41, cc-version devuelve 0341. P.ej:

#arch/i386/Makefile
cflags-y += $(shell /
if [ $(call cc-version) -ge 0300 ] ; then /
        echo "-mregparm=3"; fi ;)

cc-ifversion devuelve el último parámetro si la versión cumple las condiciones. Los ejemplos son los siguientes:

#fs/reiserfs/Makefile
ccflags-y := $(call cc-ifversion, -lt, 0402, -O1)

Si la versión $ (CC) es inferior a 4.2, ccflags-y será igual a -O1.

cc-fullversion proporciona información de versión más detallada, por ejemplo:

#arch/powerpc/Makefile
$(Q)if test "$(call cc-fullversion)" = "040200" ; then /
       echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; /
       false ; /
fi

2.5.5. cc-cross-prefix

cc-cross-prefixSe usa para verificar si el prefijo dado $(CC)existe, si existe, devuelve el primer prefijo coincidente; de ​​lo contrario, devuelve vacío. Si es necesario hacer coincidir varios prefijos, use un solo espacio para separar cada prefijo. P.ej:

#arch/m68k/Makefile
ifneq ($(SUBARCH),$(ARCH))
      ifeq ($(CROSS_COMPILE),)
           CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-)
      endif
endif

(注:本文所述内容来自kernel-2.6.30/Documentation/kbuild/makefiles.txt,适用于Linux 2.6内核)

3. Sistema de compilación del kernel de Linux

A partir del kernel 2.6 de Linux, el sistema Kbuild se utiliza para compilar el kernel de Linux, que es muy diferente del sistema de compilación anterior, especialmente para la compilación de módulos del kernel de Linux. Bajo el nuevo sistema, el sistema de compilación de Linux escaneará el Makefile de Linux dos veces: primero, el sistema de compilación leerá el Makefile en la parte superior del kernel de Linux y luego leerá el Makefile de Kbuild por segunda vez para compilar el kernel de Linux en función de lo que se lee.

3.1.Clasificación de Makefile del kernel de Linux

  • Kernel Makefile
    Kernel Makefile se encuentra en el directorio superior del código fuente del kernel de Linux, también llamado Top Makefile. Se utiliza principalmente para especificar y compilar archivos de objetos del kernel de Linux (vmlinux) y módulos (módulo). Al compilar el kernel o módulo, este archivo se leerá primero y las variables de entorno de compilación se configurarán de acuerdo con el contenido leído. Para los desarrolladores de kernel o controladores, este archivo apenas necesita modificaciones.

  • Kbuild Makefile
    El sistema Kbuild utiliza Kbuild Makefile para compilar el núcleo o los módulos. Cuando se analiza el Kernel Makefile, Kbuild leerá el Kbuild Makefile relevante para compilar el kernel o los módulos. Kbuild Makefile tiene una sintaxis específica para especificar cuáles se compilan en el kernel, cuáles se compilan en módulos y cuáles son los archivos fuente correspondientes. Los desarrolladores de kernel y controladores deben escribir este Kbuild Makefile.

  • ARCH Makefile
    ARCH Makefile se encuentra en ARCH / $ (ARCH) / Makefile, que es el Makefile del sistema correspondiente a la plataforma. Kernel Top Makefile incluirá este archivo para especificar información relacionada con la plataforma. Solo los desarrolladores de plataformas se preocuparán por este archivo.

3.2. Makefile de Kbuild

El nombre de archivo de Kbuild Makefile no es necesariamente Makefile, aunque se recomienda el nombre Makefile. El nombre de la mayoría de los archivos Kbuild es Makefile. Para distinguirlo de otros archivos Makefile, también puede especificar el nombre del Makefile de Kbuild como Kbuild. Y si los archivos "Makefile" y "Kbuild" existen al mismo tiempo, el sistema Kbuild utilizará el archivo "Kbuild".


  • Una de las funciones principales de la definición de destino Kbuild Makefile es especificar qué compilar. Esta función es obj-? Y xxx-objs especificada por los siguientes dos objetos:

    • obj-?
      obj-? especificar qué compilar y cómo compilar? El "?" Puede ser "y" o "m", "y" especifica que el objeto se compila en el kernel y "m" especifica que el objeto se compila en un módulo. La sintaxis es la siguiente;
      obj-? = $(target).o
      destino es el nombre del objeto compilado. Si no se especifica xxx-objs, los archivos fuente necesarios para compilar este objeto son $(target).c或$(target).s. Si se especifica $(target)-objs, el archivo de origen necesario para compilar este objeto lo $(target)-objsespecifica el 不能有$(target).c 或$(target).sarchivo.

    • xxx-objs
      xxx-objs especifica los archivos que necesita el objeto compilado. Generalmente, solo es necesario cuando hay varios archivos fuente.

    Siempre que se incluyan estas dos líneas, Kbuild Makefile debería funcionar.

  • Compilación anidada
    A veces, un objeto puede estar incrustado en el directorio de otro objeto, entonces, ¿cómo compilar los objetos en los subdirectorios? De hecho, es muy simple, siempre que el obj_?objeto especificado sea ​​el nombre del subdirectorio:
    obj-? = $(sub_target)/
    donde "?" Puede ser "y" o "m", que $(sub_target)es el nombre del subdirectorio.

  • Opciones del compilador
    Aunque en la mayoría de los casos no es necesario especificar las opciones del compilador, a veces aún necesitamos especificar algunas opciones del compilador.

    • ccflags-y, asflags-y y ldflags-y
      Estas opciones de compilación se utilizan para especificar las opciones de compilación de cc, as y ld

3.3. Compilar módulos externos

A veces necesitamos compilar módulos del kernel fuera del árbol de fuentes del kernel.Los comandos básicos para la compilación son:

make -C $(KERNEL_DIR) M=`pwd` modules

Podemos integrar este comando en el Makefile para que podamos ingresar el comando "make". Recuerde el Makefile del capítulo anterior, que integra el Makefile normal y el Makefile Kbuild en un solo archivo. Para distinguir entre Kbuild Makefile y Normal Makefile, reescribimos Makefile en el siguiente formulario y agregamos Kbuild Makefile- "Kbuild".

##Makefile
ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)
.PHONY: modules
default: modules
modules:
        make -C $(KERNEL_DIR)  M=$(MODULEDIR) modules
clean distclean:
        rm -f *.o *.mod.c .*.*.cmd *.ko
        rm -rf .tmp_versions
endif

## Kbuild Makefile

## Kbuild
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
obj-m   := $(MODULE_NAME).o

Generalmente, no es necesario incluir el siguiente código en el Makefile, que está escrito para que sea compatible con la versión anterior del sistema Kbuild. La variable KERNELRELEASE se define en el Kernel Makefile, por lo que el contenido de Kbuild se analizará solo cuando Kbuild lea el Makefile por segunda vez.

ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
...
endif

Archivos de encabezado externos
A veces es necesario conectar los archivos de encabezado del sistema fuera del código fuente del kernel, pero los archivos de encabezado del sistema predeterminados del sistema Kbuild están dentro del código fuente del kernel. Esto se puede hacer con la ayuda de las reglas especiales del sistema Kbuild:

  • EXTRA_CFLAGS
    EXTRA_CFLAGS puede agregar un archivo de encabezado del sistema externo al sistema Kbuild.
    EXTRA_CFLAGS += $(ext_include_path)
    Generalmente, el archivo de encabezado externo puede estar ubicado en el directorio del archivo fuente del módulo externo. ¿Cómo especificarlo? Esto se puede hacer con la ayuda de $(src)o$(obj)
  • $ (src) / $ (obj)
    $(src)es una ruta relativa, que es la ruta donde se encuentra el archivo Makefile / Kbuild. La misma $(obj)es la ruta donde se guarda el destino de la compilación, y la ruta predeterminada es la ruta donde se encuentra el código fuente.

Supongo que te gusta

Origin blog.csdn.net/houxiaoni01/article/details/103561563
Recomendado
Clasificación