下面是最简易的单文件单模块编译,假设我们要将源文件 chrdevbase.c 编译成 ko 文件。
KERNEL_DIR := /home/pigeon/workspace/imx6ull-kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CURRENR_DIR := $(shell pwd)
obj-m := chrdevbase.o
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) modules
.PHONY:clean
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) clean
KERNEL_DIR 代表内核源码的位置,后续 make modules 会用到
CURRENR_DIR := xxx
CURRENR_DIR 代表当前模块源文件所在的路径
obj-m := chrdevbase.o
obj-m 表示把文件 chrdevbase.o 作为"模块"编译,不会编译进内核,但会生成一个独立的 ko 文件
obj-y 则是直接编译进内核,即加入到内核源码中
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENR_DIR) modules
这一句我们拆成两个阶段,由简入繁分析。-C $(KERNEL_DIR) 代表切换工作目录,因为内核源码顶层的Makefile文件定义了伪目标 modules,所以要先将工作目录切换到内核源码顶层 Makefile 所在位置。
make modules -C $(KERNEL_DIR)
M=$(CURRENR_DIR) 表示回到当前路径继续执行当前的Makefile。这个可以让makefile 回到自己所指定的目录下查找模块源码,将其编译,生成 ko 文件。
make modules -C $(KERNEL_DIR) M=$(CURRENR_DIR)
整个流程可以这么理解:先执行-C $(KDIR) ,指明跳转到内核源码目录下读取那里的Makefile;再M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
具体执行流程可参考下面几篇文章:
make -C M= modules (linux下模块makefile基本结构)-xiao_zheng_jia-ChinaUnix博客
【Linux驱动】内核模块编译 —— make modules 的使用(单模块编译、多模块编译)_linux编译模块_仲夏夜之梦~的博客-CSDN博客