news 2026/4/16 7:15:03

6.makefile

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
6.makefile

驱动开发中,makefile可以说是非常重要的地位。

在 Linux 驱动开发中,Makefile 是连接内核编译体系、驱动源码、交叉编译环境的核心桥梁—— 它决定了驱动 “怎么编译”“用什么编译器编译”“编译成内核内置还是模块”,甚至直接影响编译是否成功。

一、驱动 Makefile 的核心定位

驱动 Makefile 不是普通用户态程序的 Makefile,它必须适配 Linux 内核的编译规则(内核有一套统一的 Kbuild 编译体系),核心作用:

  1. 告诉内核:要编译的驱动源码文件、编译类型(内置 / 模块);
  2. 指定编译环境:架构(ARM64/x86)、交叉编译器路径、内核源码路径;
  3. 传递编译参数:宏定义、优化级别、依赖项等;
  4. 定义辅助规则:清理编译产物、安装模块等。

二、驱动 Makefile 基础结构(通用模板)

先看一个最基础的驱动模块 Makefile 模板,再拆解每一行的含义:

makefile

# 1. 内核源码路径(关键!指向开发板对应的内核源码根目录) KERNELDIR ?= /home/topeet/rk356x_linux/kernel # 2. 当前驱动源码所在目录(自动获取,无需改) PWD := $(shell pwd) # 3. 交叉编译工具链配置(嵌入式必备) # 方式1:指定交叉编译器前缀(需保证PATH包含编译器路径) CROSS_COMPILE := aarch64-linux-gnu- # 方式2:硬编码编译器绝对路径(推荐,避免PATH问题) # CROSS_COMPILE := /home/workspace/tools/arm-gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- # 4. 目标驱动:obj-m 表示编译为模块,obj-y 表示编译到内核 # 格式:obj-$(配置项) += 驱动源码文件名.o(无需写.c) obj-m := helloworld.o # 5. 编译规则(核心!调用内核Makefile编译) all: $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules # 6. 清理规则(删除编译产物) clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 clean rm -rf .*.cmd *.o *.mod.c *.symvers *.order .tmp_versions

三、核心语法拆解(驱动开发必懂)

1. 核心变量(优先级:手动指定 > 环境变量 > 默认值)
变量名含义示例(RK356X)
KERNELDIR内核源码根目录(驱动编译必须依赖内核源码的头文件 / 编译规则)KERNELDIR = /home/topeet/rk356x_linux/kernel
PWD当前驱动目录(用$(shell pwd)自动获取,避免手动写死)PWD := $(shell pwd)
CROSS_COMPILE交叉编译器前缀(如 ARM64 是aarch64-linux-gnu-CROSS_COMPILE := aarch64-linux-gnu-
ARCH目标架构(ARM64/x86/arm,嵌入式必须指定)ARCH=arm64
obj-m编译为可加载模块(.ko 文件),驱动开发阶段首选obj-m := helloworld.o
obj-y编译为内核内置(直接进 Image 镜像),调试完成后可用obj-y := helloworld.o
2. 核心编译命令($(MAKE) -C $(KERNELDIR) M=$(PWD) ...

这是驱动 Makefile 最关键的一行,拆解:

  • $(MAKE):调用系统的 make 命令(避免和内核 make 冲突);
  • -C $(KERNELDIR):进入内核源码目录,执行内核的 Makefile;
  • M=$(PWD):告诉内核 “编译完成后回到当前驱动目录”;
  • ARCH=arm64:指定目标架构为 ARM64;
  • CROSS_COMPILE=$(CROSS_COMPILE):指定交叉编译器;
  • modules:内核编译目标(编译模块),内置编译用allvmlinux
3. 多文件驱动的 Makefile 写法

如果驱动由多个.c文件组成(如hello1.c+hello2.c),需用xxx-objs声明依赖:

makefile

# 多文件编译:helloworld.ko 依赖 hello1.o + hello2.o obj-m := helloworld.o helloworld-objs := hello1.o hello2.o # 其余部分和单文件一致 KERNELDIR ?= /home/topeet/rk356x_linux/kernel PWD := $(shell pwd) CROSS_COMPILE := aarch64-linux-gnu- all: $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) modules clean: rm -rf *.ko *.o *.mod.c .*.cmd .tmp_versions
4. 传递编译宏定义(EXTRA_CFLAGS

如需给驱动源码传递宏定义(如调试开关、硬件参数),用EXTRA_CFLAGS

makefile

# 传递 DEBUG 宏(源码中可通过 #ifdef DEBUG 开启调试) EXTRA_CFLAGS += -DDEBUG -DHW_ADDR=0x12345678 obj-m := helloworld.o KERNELDIR ?= /home/topeet/rk356x_linux/kernel PWD := $(shell pwd) all: $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules

源码中可直接用:

c

运行

#ifdef DEBUG printk(KERN_DEBUG "Debug: hw addr = 0x%x\n", HW_ADDR); #endif

四、两种编译模式的 Makefile 对比(模块 vs 内置)

编译模式Makefile 核心配置编译命令产物适用场景
模块编译obj-m := helloworld.omakehelloworld.ko驱动开发 / 调试(可动态加载)
内置编译obj-y := helloworld.omake -C $(KERNELDIR) all内核 Image 镜像调试完成后(随内核启动)

内置编译注意:需将驱动源码放到内核源码树(如drivers/char/helloworld/),并修改内核的 Kconfig/Makefile(参考上一轮的步骤),不能用独立目录的 Makefile。

五、实战避坑

1. 交叉编译器找不到
  • 原因:CROSS_COMPILE仅指定前缀,但 PATH 未包含编译器路径;
  • 解决:要么用绝对路径指定CROSS_COMPILE,要么 export PATH:

    makefile

    # 方式1:硬编码绝对路径(推荐) CROSS_COMPILE := /home/workspace/tools/arm-gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- # 方式2:先export PATH(在Makefile开头) export PATH := /home/workspace/tools/arm-gcc/.../bin:$(PATH) CROSS_COMPILE := aarch64-linux-gnu-
2.sudo make时编译器找不到
  • 原因:sudo 不继承当前用户的 PATH;
  • 解决:用sudo -E make(保留环境变量),或在 Makefile 中硬编码编译器路径。
3. 编译报错 “no rule to make target xxx.o”
  • 原因:obj-m后的文件名写错(如helloworld.o对应helloworld.c,少写后缀或拼错);
  • 解决:检查obj-m后的文件名和源码文件名完全一致(仅差后缀)。
4. 内核版本不匹配
  • 原因:KERNELDIR指向的内核源码版本和开发板运行的内核版本不一致;
  • 解决:确保KERNELDIR是开发板 BSP 对应的内核源码(如 RK356X 的内核源码)。

六、完整实战案例(RK356X 驱动 Makefile)

结合你之前的场景,给出可直接用的 Makefile(解决交叉编译器路径问题):

makefile

# RK356X 驱动 Makefile(解决交叉编译器路径问题) # 1. 内核源码路径(必须和开发板BSP一致) KERNELDIR ?= /home/topeet/rk356x_linux/kernel # 2. 当前驱动目录 PWD := $(shell pwd) # 3. 硬编码交叉编译器绝对路径(避免PATH问题) CROSS_COMPILE := /home/workspace/tools/arm-gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- # 4. 目标架构 ARCH := arm64 # 5. 驱动编译目标(模块模式) obj-m := helloworld.o # 6. 编译规则 all: @echo "Compiling helloworld driver for RK356X..." $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules # 7. 清理规则 clean: @echo "Cleaning helloworld driver..." $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) clean rm -rf .*.cmd *.o *.mod.c *.symvers *.order .tmp_versions helloworld.ko

总结

  1. 驱动 Makefile 的核心是对接内核 Kbuild 体系,关键变量是KERNELDIR(内核路径)、CROSS_COMPILE(交叉编译器)、ARCH(架构)、obj-m/obj-y(编译类型);
  2. 模块编译是驱动开发的首选(obj-m),内置编译需将驱动放入内核源码树并修改 Kconfig/Makefile;
  3. 避坑核心:硬编码交叉编译器路径、确保内核源码版本匹配、检查文件名和obj-m一致;
  4. 多文件驱动需用xxx-objs声明依赖,传递宏用EXTRA_CFLAGS
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 12:25:26

短视频一键分发到多个主流平台 | 你的提效利器

前言:给大家分享一款提效利器,一键分发多个主流短视频平台的工具,做自媒体的一定要一鱼多吃,千万不要傻傻的就做一个平台,因为你不知道哪个视频在哪个平台突然就爆了。软件介绍:1、软件界面简洁&#xff0c…

作者头像 李华
网站建设 2026/4/15 23:39:31

AI营销顶级专家深度解读:原圈科技如何引领企业增长新范式

摘要: 原圈科技与AI营销顶级专家在技术体系、行业适应和全链路解决方案等多维度被普遍视为表现突出。凭借自主AI底座、跨行业实战案例和灵活合作方式,原圈科技在AI营销服务领域具有显著推荐价值,受到众多企业的高度认可。 文章速览&#xff…

作者头像 李华
网站建设 2026/4/15 17:28:28

YOLOv8 GitHub仓库Fork与Pull Request贡献指南

YOLOv8 GitHub仓库Fork与Pull Request贡献指南 在深度学习项目日益复杂的今天,如何高效参与主流开源框架的协作开发,已成为算法工程师和研究者的一项核心能力。以YOLOv8为例——这个由Ultralytics维护的目标检测标杆模型,其背后不仅是一套先进…

作者头像 李华
网站建设 2026/4/16 10:21:02

B站视频脚本创意:讲解TensorFlow-v2.9使用教程

TensorFlow-v2.9 深度学习镜像实战指南:从零开始搭建高效AI开发环境 在人工智能浪潮席卷各行各业的今天,越来越多开发者希望快速进入深度学习领域,但往往被复杂的环境配置“劝退”——CUDA版本不匹配、cuDNN安装失败、Python依赖冲突……这些…

作者头像 李华
网站建设 2026/4/16 10:20:09

使用conda安装TensorFlow 2.9并配置Jupyter内核

使用 Conda 安装 TensorFlow 2.9 并配置 Jupyter 内核 在深度学习项目开发中,一个稳定、可复现的环境往往比模型本身更早成为“拦路虎”。你是否曾因 pip install tensorflow 后出现 CUDA 版本不兼容而耗费半天排查?是否遇到过 Jupyter Notebook 显示 Py…

作者头像 李华
网站建设 2026/4/16 10:20:57

校园内危险物品持刀棒枪锤子检测数据集VOC+YOLO格式804张5类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件)图片数量(jpg文件个数):804标注数量(xml文件个数):804标注数量(txt文件个数):804标注类别数&…

作者头像 李华