【嵌入式Linux】编译应用和ko内核模块Makefile使用记录

您所在的位置:网站首页 如何编译ko文件 【嵌入式Linux】编译应用和ko内核模块Makefile使用记录

【嵌入式Linux】编译应用和ko内核模块Makefile使用记录

2024-06-02 17:56| 来源: 网络整理| 查看: 265

文章目录 一、常用的语法1.1 `=, :=, +=, ?=`的区别1.2 命名模式:target-objs 和 target-y 的区别 二、编译KO2.1 难度0:一个.c文件编译成一个.ko文件2.1.1 改进一下Makefile使得编译命令只需要make就可以 2.2 难度1:多个.c,.h文件编译成一个.ko文件风格二 三、编译应用3.1 最简单的:只有一个.c文件编译没有必要写Makefile3.2 风格一:编译时直接make 四、错误记录4.1 编译内核模块报错1:cc1: some warnings being treated as errors4.2 编译内核模块报错2

一、常用的语法 1.1 =, :=, +=, ?=的区别

在Makefile中,变量的赋值可以使用以下几种方式:

=:最基本的赋值符号,表示简单的延迟展开(lazy expansion)方式。变量的值将会在使用变量的时候进行展开。

:=:立即展开(immediate expansion)的赋值方式。变量的值在赋值的时候立即展开,并且在后续的使用中不再改变。

+=:追加赋值符号,用于将值追加到变量的原有值的末尾。

?=:条件赋值符号,用于在变量未定义或为空时才进行赋值。

下面是每种符号的示例和解释:

VARIABLE1 = Hello $(VARIABLE2) VARIABLE2 = World VARIABLE3 := Hello $(VARIABLE4) VARIABLE4 := World VARIABLE5 += Good VARIABLE5 += Morning VARIABLE6 ?= Default Value all: @echo "VARIABLE1:" $(VARIABLE1) @echo "VARIABLE3:" $(VARIABLE3) @echo "VARIABLE5:" $(VARIABLE5) @echo "VARIABLE6:" $(VARIABLE6)

输出结果为:

VARIABLE1: Hello $(VARIABLE2) VARIABLE3: Hello VARIABLE5: Good Morning VARIABLE6: Default Value

可以看到,= 进行简单赋值,使用时才展开。:= 进行立即展开,赋值时就展开为确定的值。+= 用于追加值,变量值累加。?= 用于条件赋值,只在变量未定义或为空时进行赋值。

1.2 命名模式:target-objs 和 target-y 的区别 target-objs:都可以,应用程序和内核模块target-y:常用于内核模块

通常,内核驱动有两种编译和加载方式:第一种是直接把驱动程序编译进内核中,对应obj-y变量;第二种是将驱动程序作为模块单独编译成.ko文件,而不编译进内核中,然后手动加载,即obj-m变量。

在Makefile中,main-objs和main-y是用于定义目标文件(object files)的变量。

main-objs是一种目标文件的变量约定,用于指定构建某个目标的源文件列表。通常,当你的目标(如可执行文件、模块)由多个源文件组成时,你可以使用target-objs的命名模式,其中target是你的目标名称。使用target-objs,你可以列出构成目标的所有源文件,例如: main-objs := file1.o file2.o file3.o main-y是另一种目标文件的变量约定,用于指定构建某个目标的源文件列表,类似于target-objs。但是,main-y通常用于内核模块(kernel module)的构建。在内核模块编译构建时,main-y变量指定要包含在模块中的所有源文件。例如: main-y := file1.o file2.o file3.o

这样,当你构建目标时,Makefile将使用所定义的target-objs或target-y变量来确定哪些源文件应该编译为目标文件,并将其链接到最终的目标(如可执行文件、模块)中。

请注意,target-objs和target-y只是约定的变量名,你可以根据自己的需要和习惯为目标定义适当的变量名。

二、编译KO 2.1 难度0:一个.c文件编译成一个.ko文件

这几乎就是最简单的内核模块了!

# 指定你的内核源码目录 KERNEL_DIR := /home/liefyuan/Liefyuan/cherry-pi/linux-zero-5.2.y # 指定你的模块源码目录:会把该目录下的文件编译成.ko文件 CURRENT_PATH := $(shell pwd) # 驱动名称: led.ko obj-m := led.o build: kernel_modules kernel_modules: $(MAKE) -C $(KERNEL_DIR ) M=$(CURRENT_PATH) modules clean: $(MAKE) -C $(KERNEL_DIR ) M=$(CURRENT_PATH) clean

编译命令:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

一般没啥问题就会在本目录下生成一个led.ko文件

2.1.1 改进一下Makefile使得编译命令只需要make就可以

Makefile

ARCH := arm CROSS_COMPILE := arm-linux-gnueabihf- KERN_DIR = /home/liefyuan/Liefyuan/cherry-pi/linux-zero-5.2.y obj-m += led.o #cc1: all warnings being treated as errors解决办法 CFLAGS = -Wall -Wpointer-arith -Wno-unused KBUILD_CFLAGS += -w all: make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(shell pwd) modules clean: rm -rf *.order *o *.symvers *.mod.c *.mod *.ko

编译命令:

make 2.2 难度1:多个.c,.h文件编译成一个.ko文件 MODULE_NAME = hci_uart ifneq ($(KERNELRELEASE),) obj-m :=$(MODULE_NAME).o $(MODULE_NAME)-y := hci_ldisc.o hci_h4.o hci_rtk_h5.o rtk_coex.o #cc1: all warnings being treated as errors解决办法 CFLAGS = -Wall -Wpointer-arith -Wno-unused KBUILD_CFLAGS += -w else PWD := $(shell pwd) KDIR := /home/liefyuan/luckfox-pico-main/sysdrv/source/kernel all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.mod *.mod.c *.mod.o *.ko *.symvers *.order *.a endif

解释一下Makefile文件。KERNELRELEASE是在内核源码的上层Makefile中定义的一个变量。在该模块未被动到内核源代码中时,这个变量不会被定义。该模块移动到内核源代码后,这个变量就有定义了。

KDIR变量表示的这个目录下存放该版本linux内核源码,其中调用的shell指令uname -r用来打印该内核的版本号。PWD是当前目录所在的路径。

在终端输入make指令后,对.c文件编译进行编译。这个过程比较复杂。首先,初次编译前变量KERNELRELEASE为空,因此执行else后面的程序,即

make -C $(KDIR) M=$(PWD) modules

-C参数的作用是指定跳转目录,-C $(KDIR)指明跳转到内核源码所在的目录并读取那里的Makefile,启动kbuild机制。M=$(PWD)再返回到当前目录继续执行当前的Makefile。

kbuild即kernel build,用于编译Linux内核文件,对Makefile进行功能上的扩展。大部分内核中的Makefile都使用kbuild进行组织,它能使原本的Makefile代码变得更简洁、高效。kbuild中会预定义一些变量,如obj-y、obj-m,用来指定要生成的.o目标文件。只需要对该变量进行赋值,kbuild就会自动把代码编译到内核或编译成模块。

通常,内核驱动有两种编译和加载方式:第一种是直接把驱动程序编译进内核中,对应obj-y变量;第二种是将驱动程序作为模块单独编译成.ko文件,而不编译进内核中,然后手动加载,即obj-m变量。本例中将DriverFramework.o赋值给obj-m变量,就是采用第二种模式,单独生成一个独立的DriverFramework.ko文件。 ———————————————— 版权声明:本文为CSDN博主「精致的螺旋线」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/baidu_38797690/article/details/122116281

编译命令:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 风格二 obj-m := ch36x.o #交叉编译需要指定内核在ubuntu的位置,内核源代码路径 KERNELDIR= /home/ht/rk3588/nvr_v1.3/kernel_rk_demo #cc1: all warnings being treated as errors解决办法 CFLAGS = -Wall -Wpointer-arith -Wno-unused KBUILD_CFLAGS += -w #交叉编译器路径 CROSS_PATH = /opt/rk_linux/rv1126_1109/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- #驱动模块源代码路径 PWD := $(shell pwd) #交叉编译 modules: $(MAKE) ARCH=arm64 $(CFLAGS) LOCALVERSION="sun50iw6" CROSS_COMPILE=$(CROSS_PATH) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.mod *.mod.c .tmp_versions modules.order Module.symvers Module.markers built-in.o ch36x.ko *.ko.* 三、编译应用 3.1 最简单的:只有一个.c文件编译没有必要写Makefile

假设文件是main.c,交叉编译成main.elf,就直接命令行输入:

arm-linux-gnueabihf-gcc main.c -o main.elf

然后本目录下就可以生成main.elf,拷贝到目标平台上就可以运行了。

3.2 风格一:编译时直接make

要想编译时直接make,就得在Makefile里面指定编译器/交叉编译器。

一个使用过的例子: Makefile文件

rtk_hciattach:hciattach.c hciattach_rtk.o arm-linux-gnueabihf-gcc -o rtk_hciattach hciattach.c hciattach_rtk.o hciattach_rtk.o:hciattach_rtk.c arm-linux-gnueabihf-gcc -c hciattach_rtk.c clean: rm -f *.o rtk_hciattach

编译:

make

然后本目录下就可以生成rtk_hciattach可执行文件了。

四、错误记录 4.1 编译内核模块报错1:cc1: some warnings being treated as errors make -C /home/liefyuan/luckfox-pico-main/sysdrv/source/kernel M=/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver modules make[1]: Entering directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel' CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_ldisc.o /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_ldisc.c: In function 'hci_uart_init': /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_ldisc.c:1149:22: error: assignment to 'ssize_t (*)(struct tty_struct *, struct file *, unsigned char *, size_t, void **, long unsigned int)' {aka 'int (*)(struct tty_struct *, struct file *, unsigned char *, unsigned int, void **, long unsigned int)'} from incompatible pointer type 'ssize_t (*)(struct tty_struct *, struct file *, unsigned char *, size_t)' {aka 'int (*)(struct tty_struct *, struct file *, unsigned char *, unsigned int)'} [-Werror=incompatible-pointer-types] hci_uart_ldisc.read = hci_uart_tty_read; ^ cc1: some warnings being treated as errors make[2]: *** [scripts/Makefile.build:273: /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_ldisc.o] Error 1 make[1]: *** [Makefile:1917: /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver] Error 2 make[1]: Leaving directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel' make: *** [Makefile:12: all] Error 2

解决办法:

编译驱动的makefile中加入下面两句

#cc1: all warnings being treated as errors解决办法 CFLAGS = -Wall -Wpointer-arith -Wno-unused KBUILD_CFLAGS += -w

为了避免内核继续将警告提示错误导致的编译失败

4.2 编译内核模块报错2 root@DESKTOP-2CFURMS:/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver# make ARCH=arm CROSS_COMPILE=arm-rockchip830-linux-uclibcgnueabihf- make -C /home/liefyuan/luckfox-pico-main/sysdrv/source/kernel M=/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver modules make[1]: Entering directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel' MODPOST /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/Module.symvers ERROR: modpost: "hci_register_dev" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "hci_recv_frame" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "hci_unregister_dev" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "bt_err" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "bt_info" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "hci_alloc_dev" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! ERROR: modpost: "hci_free_dev" [/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko] undefined! make[2]: *** [scripts/Makefile.modpost:169: /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/Module.symvers] Error 1 make[2]: *** Deleting file '/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/Module.symvers' make[1]: *** [Makefile:1819: modules] Error 2 make[1]: Leaving directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel' make: *** [Makefile:12: all] Error 2

来源:https://github.com/espressif/esp-hosted/issues/110 kernel没有编译支持Bluetooth的功能,建议通过make menuconfig来配置蓝牙相关功能后再编译内核,最后再来编译.ko。 在这里插入图片描述

浑身通透。我居然理解了他的意思。 卧槽,牛逼!!!试了一下,KO编译出来了!!!

root@DESKTOP-2CFURMS:/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver# make ARCH=arm CROSS_COMPILE=arm-rockchip830-linux-uclibcgnueabihf- make -C /home/liefyuan/luckfox-pico-main/sysdrv/source/kernel M=/home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver modules make[1]: Entering directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel' CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_ldisc.o CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_h4.o CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_rtk_h5.o CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/rtk_coex.o LD [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.o MODPOST /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/Module.symvers CC [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.mod.o LD [M] /home/liefyuan/luckfox-pico-main/project/app/rkwifibt-1.0.0/realtek/bluetooth_uart_driver/hci_uart.ko make[1]: Leaving directory '/home/liefyuan/luckfox-pico-main/sysdrv/source/kernel'

Makefile文件

MODULE_NAME = hci_uart ifneq ($(KERNELRELEASE),) obj-m :=$(MODULE_NAME).o $(MODULE_NAME)-y := hci_ldisc.o hci_h4.o hci_rtk_h5.o rtk_coex.o CFLAGS = -Wall -Wpointer-arith -Wno-unused KBUILD_CFLAGS += -w else PWD := $(shell pwd) KDIR := /home/liefyuan/luckfox-pico-main/sysdrv/source/kernel all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.mod *.mod.c *.mod.o *.ko *.symvers *.order *.a endif


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3