简体   繁体   中英

How to provide -C option in the Makefile for cross-compiling kernel module?

I'm trying to build a simple kernel module for arm64 machine from my x86_64 machine. The target and host are both using ubuntu 20.04 as OS. First I tried building a simple kernel module for the host (x86_64) using this Makefile. By the way, uname -r gives 5.4.0-77-generic in my case.

obj-m += chr_drv_ex1.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

The program builds and runs ok.

Now I want to try it for arm64 ubuntu 20.04 machine target (I have a virtual machine). One idea is to copy the /lib/modules/5.4.0-77-generic/build directory from the arm64 machine and use the folder as the -C option for my cross-compile. But I soon found that this 'build' directory a symbolic link to /usr/src/linux-headers-5.4.0-77-generic and many files or directories there are also symbolic links to those under /usr/src/linux-headers-5.4.0-77. So I need to copy the /lib/modules/5.4.0-77-generic, /usr/src/linux-headers-5.4.0-77 and /usr/src/linx-headers-5.4.0-77-generic. And this doesn't seem nice.

So my question is: how should I provide the -C option (where build scripts are located) in this case? Can I just install linux-headers-5.4.0-77 and linux-headers-5.4.0-77-generic in my host system and use them? (I tried it but I have this compile error:

make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -C /lib/modules/5.4.0-77-generic/build M=/home/ckim/pprj/qemu_test/test_ldd modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-77-generic'
  CC [M]  /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.o
In file included from ./include/linux/types.h:6,
                 from ./include/linux/limits.h:6,
                 from ./include/linux/kernel.h:7,
                 from /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.c:1:
./include/uapi/linux/types.h:5:10: fatal error: asm/types.h: No such file or directory
    5 | #include <asm/types.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.build:271: /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.o] Error 1
make[1]: *** [Makefile:1762: /home/ckim/pprj/qemu_test/test_ldd] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-77-generic'
make: *** [Makefile:4: all] Error 2

@Tsyvarev told me in his comment that I should actually build the kernel and the -C option should point to the kernel build directory. So here is what I did with a little more search. (Thanks @Tsyvarev !)

Suppose you are in the directory where you have your kernel module *.c source program ( chr_drv_ex1.c here) and the Makefile , and I have copied /boot/config-5.4.0-77-generic from a virtual machine that I'm making the kernel module for to ./u20_config . To get the .config file for the currently running kernel, see here .

sudo apt install linux-source-5.4.0 (/usr/src/linux-source-5.4.0 is installed)
tar -xf /usr/src/linux-source-5.4.0/linux-source-5.4.0.tar.bz2
cd linux-source-5.4.0
cp ../u20_config .config (u20_config is from ubuntu-20.04 VM)
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j`nproc`

cd ..
make (this builds kernel module and app, see Makefile)

And this is the Makefile I used (test_chr_drv is the application using the driver).

export CROSS_COMPILE:=aarch64-none-linux-gnu-
export ARCH:=arm64
obj-m += chr_drv_ex1.o
export KDIR:=linux-source-5.4.0

all: test_chr_drv
    make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) modules

clean:
    make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) clean
    rm -f test_chr_drv

test_chr_drv: test_chr_drv.c
    $(CROSS_COMPILE)gcc $^ -o $@

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM