每天复习一点,今天是Makefile文件的理解和使用

太久没做模块化编译了,导致简单的模块编译安装都得翻书,今天趁着,需要给开发板装CH9344SER的串口驱动,做个笔记。

首先,我的开发板是定制的内核,所以想直接在开发板上编译和安装,有点麻烦,所以,我用最简单的方法,交叉编译,再移植到开发板,但是问题来,这也是我犯的第一个错误,我知道得用交叉编译器,也知道要arm格式编译,但是忘了内核版本不同!!!!!!!!

一:回到正题,先看原来官网的CH9344的Makefile

ifeq ($(KERNELRELEASE), )
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR)  M=$(PWD)  
clean:
	rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:
	insmod ch9344.ko
unload:
	rmmod ch9344
install: default
	insmod ch9344.ko || true
	mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
	cp -f ./ch9344.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
	depmod -a
uninstall:
	rmmod ch9344 || true
	rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch9344.ko || true
	depmod -a
else
	obj-m := ch9344.o
endif

1. 判断内核环境

ifeq ($(KERNELRELEASE), )

  • ifeq ($(KERNELRELEASE), ):判断变量 KERNELRELEASE 是否为空。
  • 如果为空,说明当前不是内核构建环境(即 make 被直接调用)。

2. 定义内核路径

KERNELDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd)

  • KERNELDIR:定义内核源码目录,通常是 /lib/modules/<内核版本>/build
    • $(shell uname -r) 获取当前系统运行的内核版本。
    • /build 是内核源码的构建目录。
  • PWD:定义当前工作目录,使用 $(shell pwd) 获取。

3. 默认目标

default: $(MAKE) -C $(KERNELDIR) M=$(PWD)

  • default:默认目标。
  • $(MAKE) -C $(KERNELDIR) M=$(PWD)
    • -C $(KERNELDIR):进入内核源码目录。
    • M=$(PWD):告诉内核构建系统在 PWD(当前目录)下构建外部模块。
    • 这是构建内核模块的标准流程。

4. 清理目标

clean: rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod

  • clean:清理编译生成的临时文件和目标文件。
  • 删除的内容包括:
    • 编译生成的 .ko(模块文件)、.o(目标文件)、.mod.c(模块依赖信息)。
    • .tmp_versions 目录(模块版本信息)、Module.symvers(符号表)。
    • 其他临时文件(如 .*.cmdmodules.order)。

5. 加载模块

load: insmod ch9344.ko

  • load:加载模块。
  • 使用 insmod 插入编译好的模块文件 ch9344.ko

6. 卸载模块

unload: rmmod ch9344

  • unload:卸载模块。
  • 使用 rmmod 卸载模块 ch9344

7. 安装模块

install: default insmod ch9344.ko || true mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true cp -f ./ch9344.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true depmod -a

  • install:安装模块。
    • 首先运行 default 目标,确保模块已编译。
    • insmod ch9344.ko || true:尝试加载模块,忽略错误。
    • mkdir -p:确保模块的目标路径存在(USB 串口驱动目录)。
    • cp -f:将模块文件复制到系统模块路径中。
    • depmod -a:更新模块依赖信息。

8. 卸载模块

uninstall: rmmod ch9344 || true rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch9344.ko || true depmod -a

  • uninstall:卸载并删除模块。
    • rmmod ch9344 || true:卸载模块,忽略错误。
    • rm -rf:删除模块文件。
    • depmod -a:更新模块依赖信息。

9. 内核构建环境

else obj-m := ch9344.o endif

  • else:当 KERNELRELEASE 不为空时,说明正在内核构建环境中。
  • obj-m := ch9344.o
    • 定义需要构建的模块文件 ch9344.o
    • 这是内核模块构建的标准语法。

到这里,应该都能大概理解这个Makefile,在做什么,假如,你的Linux环境是标准内核,可以联网更新的内核,配置好编译环境,直接make编译就可以

而我要说的是不同内核应该怎么改,以下是我自己的实例模板,自己参考修改。 

# 指定 KERNELDIR,使用厂商内核路径,一般在SDK里,没有SDK的话,可以单独找内核文件就行
KERNELDIR ?= /path/to/sdk-toolchain/kernel

# 当前代码目录
PWD := $(shell pwd)

# 指定交叉编译工具链前缀,这个可以是厂商提供的SDK里的工具也可以是自己装的交叉编译
CROSS_COMPILE := /path/to/sdk-toolchain/bin/aarch64-none-linux-gnu-

# 指定目标架构
ARCH := arm64

# 编译目标
obj-m := ch9344.o

# 默认规则
default:
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules

# 清理规则
clean:
	rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions modules.order Module.symvers

# 安装模块规则(可选,用于将模块复制到开发板)
install:
	scp ch9344.ko user@<开发板IP地址>:/lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/

# 卸载模块规则(可选,用于从开发板卸载模块)
uninstall:
	ssh user@<开发板IP地址> "rmmod ch9344; rm -f /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ch9344.ko"

最后去开发板上查看

 modinfo ch9344.ko 验证 vermagic 是否与开发板内核版本一致

在开发板上加载模块:

sudo insmod /lib/modules/<开发板内核版本>/kernel/drivers/usb/serial/ch9344.ko

 这就完成了,

温故而知新,以前学习的时候不爱做笔记,现在用到了,都记不住,做点笔记,至少能快速翻阅,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值