2011-04-19 13 views
5

Estoy confrontando el sistema de compilación del kernel de Linux (Kbuild, kernel ≥2.6.28) con la estructura de directorios y el sistema de compilación para un proyecto más grande. Nuestro proyecto contiene un módulo del núcleo Linux fuera del árbol, y nuestra estructura de directorios se parece a esto (simplificado, obviamente):Construyendo un módulo kernel de Linux fuera de árbol en un directorio de objetos separado

checkout/src/common/*.c   source files (common to Linux and other platforms) 
checkout/src/linux-driver/*.c  source files (for the Linux kernel driver) 
checkout/build/linux/Kbuild  Kbuild 
tmp/linux-2.6.xx/     where the Linux kernel is unpacked and configured 
output/linux-arm-debug/   where object files must end up 

El proceso de construcción No hay que modificar nada bajo checkout, y construir el módulo debe no modificar nada en tmp/linux-2.6.xx. Todos los archivos de salida deben terminar en output/linux-arm-debug (o cualquier variante de arquitectura y depuración que se haya seleccionado en el momento de la compilación).

He leído kbuild/modules.txt, y empecé a escribir mi archivo Kbuild:

MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG) 
obj-m += $(MOD_OUTPUT_DIR)/foo_mod.o 
$(MOD_OUTPUT_DIR)/our_module-objs := $(MOD_OUTPUT_DIR)/foo_common.o $(MOD_OUTPUT_DIR)/foo_linux.o 

Este se encarga de almacenar los ficheros objeto en un directorio diferente de donde Kbuild vidas. Ahora, ¿cómo puedo especificar que foo_common.o necesita ser compilado desde …/checkout/src/common/foo_common.c y foo_linux.o desde …/checkout/src/linux-driver/foo_linux.c?

Respuesta

0

Si bien no ha mencionado lo que ha intentado hasta ahora (o si ya encontró una solución), parece que solo necesita continuar un poco más abajo en el archivo modules.txt - a Sección 4.3:

--- 4.3 Several Subdirectories 

kbuild can handle files that are spread over several directories. 
Consider the following example: 

. 
|__ src 
| |__ complex_main.c 
| |__ hal 
| |__ hardwareif.c 
| |__ include 
|  |__ hardwareif.h 
|__ include 
    |__ complex.h 

To build the module complex.ko, we then need the following 
kbuild file: 

    --> filename: Kbuild 
    obj-m := complex.o 
    complex-y := src/complex_main.o 
    complex-y += src/hal/hardwareif.o 

    ccflags-y := -I$(src)/include 
    ccflags-y += -I$(src)/src/hal/include 

As you can see, kbuild knows how to handle object files located 
in other directories. The trick is to specify the directory 
relative to the kbuild file's location. That being said, this 
is NOT recommended practice. 

For the header files, kbuild must be explicitly told where to 
look. When kbuild executes, the current directory is always the 
root of the kernel tree (the argument to "-C") and therefore an 
absolute path is needed. $(src) provides the absolute path by 
pointing to the directory where the currently executing kbuild 
file is located. 
+3

he leído esa parte, y estoy en una pérdida en cuanto a cómo esto me ayuda. En ese ejemplo, 'complex_main.c' y' complex_main.o' están en el mismo directorio.En mi árbol de compilación, las fuentes y los productos de compilación están completamente separados. – Gilles

1

Mi solución poco elegante pero eficaz es copiar los archivos de origen en el árbol de salida.

FOO_SOURCES_DIR = $(src)/../../../checkout/src 
FOO_MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG) 

# Specify the object files 
obj-m += $(FOO_MOD_OUTPUT_DIR)/foo_mod.o 
FOO_MODULE_OBJS := $(FOO_MOD_OUTPUT_DIR)/foo_common.o $(FOO_MOD_OUTPUT_DIR)/foo_linux.o 
$(FOO_MOD_OUTPUT_DIR)/foo_mod-objs := $(FOO_MODULE_OBJS) 

# Where to find the sources 
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_common.c: $(FOO_SOURCES_DIR)/common/foo_common.c 
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_linux.c: $(FOO_SOURCES_DIR)/linux-driver/foo_linux.c 

# Rules to copy the sources 
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS)) 
$(FOO_COPIED_SOURCES): 
     $(Q)mkdir -p $(@D) 
     cp -f $< [email protected] 
clean-files += $(FOO_COPIED_SOURCES) 
clean-dirs += $(FOO_MOD_OUTPUT_DIR) 
+0

Copiar? ¡Por lo menos, haz enlaces simbólicos _once_ y luego déjalo en paz! – Shahbaz

+1

@Shahbaz Los enlaces simbólicos no siempre funcionan en los árboles de compilación. Tienden a ser incluidos como enlaces simbólicos en los archivos. Incluso tuve que trabajar en las exportaciones de Samba en algún momento (ugh). Copiar un puñado de archivos fuente en un árbol de compilación del kernel de Linux es cacahuetes. – Gilles

0

Un poco tarde, pero parece que O= flag es lo que necesita.

+0

Se ve bien. Me sorprendería si no lo hubiera intentado, pero ha pasado un tiempo y he pasado a otros proyectos, así que honestamente no puedo estar seguro. Gracias por su sugerencia, intentaré encontrar la oportunidad de probarlo. – Gilles

+3

No funciona para mí, parece que 'O =' y 'KBUILD_OUTPUT' deben aplicarse ambos en el punto donde construyes el kernel en sí, no solo los módulos externos. Lo que veo es errores al encontrar archivos generados dentro del árbol de fuentes, por ejemplo 'linux/version.h' - los busca en la ubicación O =. – Greg

0

Puede establecer la variable de entorno KBUILD_OUTPUT. Esto funciona de manera similar a la opción O=; sin embargo, dado que es una variable de entorno, puede abarcar múltiples archivos make donde no se puede pasar O= o necesita construirse un módulo fuera de directorio. Estaba teniendo el mismo problema al tratar de crear un conjunto de módulos compat-wireless y necesitaba usar O= para la construcción real de la imagen del kernel.

3

Tuve un problema similar. Modifiqué linux_2_6_34/scripts/Makefile.build de la siguiente manera.

ifdef SRCDIR 
src := $(SRCDIR) 
else 
src := $(obj) 
endif 

SRCDIR es el origen de directorio.

para compilar el módulo y como realizar

make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)` 
+0

Tan cerca, los archivos c compilados, pero se niega a dar el paso final para generar el '.ko' (versión 3.14.0) – Greg

+0

Lo siento - pebcak - tuve un error en mi Kbuild - esto funciona bien - con el con la condición de que se confunde un poco acerca de qué directorio y en una etapa requiere que el archivo Kbuild esté en ambos directorios. Es un pequeño precio a pagar para ponerlo en funcionamiento – Greg

+0

Esto parece funcionar, pero por alguna razón necesito tener un Makefile vacío en el directorio de salida para que esto funcione (linux-4.1.6) –

2

Aquí es un Makefile, que hace de fuente de árboles construye para los módulos de kernel de árboles (adaptado de @ comentarios de Mark) ...

KDIR ?= /lib/modules/$(shell uname -r)/build 
BUILD_DIR ?= $(PWD)/build 
BUILD_DIR_MAKEFILE ?= $(PWD)/build/Makefile 

default: $(BUILD_DIR_MAKEFILE) 
    make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules 

$(BUILD_DIR): 
    mkdir -p "[email protected]" 

$(BUILD_DIR_MAKEFILE): $(BUILD_DIR) 
    touch "[email protected]" 

clean: 
    make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean 

Nota: Usted todavía necesita un archivo kbuild ...

obj-m += my_driver.o 
+0

No entendí por qué todavía necesitamos un archivo de Kbuild 'obj-m + = my_driver.o' –

+0

Es solo una cuestión de preferencia. Si lo desea, puede agregar esta línea al Makefile. Ponerlo en el archivo de Kbuild simplifica el archivo Makefile eliminando la prueba 'ifneq ($ (KERNELRELEASE),)' utilizada para proteger esta declaración en el archivo Makefile. Ver: http://www.makelinux.net/ldd3/chp-2-sect-4.shtml –

+0

Esto está muy cerca de lo que necesito, pero tristemente asume que el módulo 'Makefile' está en' src' directorio, que no es el caso para mí (está siendo construido por autoconf, entonces 'Makefile.in' está en la fuente y' Makefile' en la compilación/M dir, y también para los archivos de Kbuild). – Miral

Cuestiones relacionadas