linux cross目录,[linux]一个通用驱动Makefile-V2-支持编译多目录

目录

前言

该 Makefile 已经通过基于内核Linux5.4

版本验证通过。

因为编写这通用驱动 Makefile 时遇到了头文件指定路径失败的问题。使用过ccflags-y 、INCDIR 、EXTRA_CFLAGS 、-L

等等参数都无效。就是因为我使用了$(shell pwd)

。导致这些参数的路径都为内核源码路径下,而非模块路径。后面重新查看内核文档,看内核的推荐写法才解决了,使用 $(src) 来获取模块源码路径。正确指向自定义的头文件路径。所以有以下建议:

建议

:对于不同的Linux

内核,应该去该内核文档看看makefiel

和Kbuild

的语法及特点。(Documentation/kbuild

)**

1. 特点

支持编译多目录Linux内核驱动

支持多目录源文件及头文件编译

兼容性高,修改接口宏即可

2. 分析

2.1 简要原理

由于驱动程序中包含了很多来自内核的头文件,编译驱动程序时需要指定板子所用的同一版本的内核源码(编译后,以下无特别说明也是编译后

)路径。

简要原理其实是主要由内核源码中的Makefile

来进行编译并生成驱动文件。所以当前 Makefile 只需要提供参数和跳转到内核源码路径执行其顶层 Makefile

即可。

2.2 具体分析

内核路径:

KERNEL_DIR = /home/lss/work/kernel/imx6/ebf-buster-linux/build_image/build

:指出编译后的内核源码路径。

架构及编译器:

ARCH = arm

:提供架构名称。

CROSS_COMPILE = arm-linux-gnueabihf-

:提供交叉编译器名称。

CC = $(CROSS_COMPILE)gcc

:用于测试用例APP使用的编译器(无测试用例可屏蔽

)。

export ARCH CROSS_COMPILE

:共享架构名称及交叉编译器名称到 sub-Makefile,这里即是内核源码中的顶层Makefile及其sub-Makefile。

路径变量:

PWD := $(shell pwd)

:运行时的 make 路径。并不是当前文件路径

MODDIR := $(src)

:当前模块的顶层路径。

内核源码原话:$(src) provides the absolute path by pointing to the directory where the currently executing kbuild file is located.Kbuild可以看作Makefile。(虽然不严谨

)

$(src) 是由内核 Makefile 提供的。为当前被执行的 子Makefile 的绝对路径。在这里也可以看出 M= 的路径。因为当内核顶层 Makefile 使用 -C 跳到内核顶层 Makefile ,如果使用$(shell pwd)

的话,该命令的值为 内核顶层 Makefile 的绝对路径,而不是内核顶层 Makefile 的路径。($(MAKE) -C $(KERNEL_DIR) M=$(CURDIR)  modules 中的 M=$(CURDIR) 例外,因为它在当前 Makefile 生效后再跳转到 -C 的

)

目标:

TARGET_DRV := led_device_driver

:模块目标名称。

TARGET_APP := led_app

:测试用例目标名称。

资源文件和模块目标定义

$(TARGET_DRV)-y += led_module.o

:目标模块所需源文件。

$(TARGET_DRV)-y += ./device/led_dev_a.o

:目标模块所需源文件。

$(TARGET_DRV)-y += ./driver/led_drv.o

:目标模块所需源文件。

obj-m := $(TARGET_DRV).o

:目标。告诉内核要编译成模块。

obj-y

:编译驱动到内核。obj-m

:编译驱动为模块。obj-n

:不编译。

驱动模块的多源文件编译

:obj-m := $(TARGET).o 是告诉 makefile 最总的编译目标。而 $(TARGET)-y 则是告诉 makefile 该总目标依赖哪些目标文件。(为固定格式,如总目标为xxx.o

,那么它依赖的源文件应该这样指定xxx-y +=

)(也可以使用 xxx-objs)

编译参数:

ccflags-y := -I$(MODDIR)/include

:指定自定义头文件路径。这里只能使用 $(src) 来获取模块文件路径。

External modules tend to place header files in a separate include/ directory where their source is located, although this is not the usual kernel style. To inform kbuild of the directory, use eitherccflags-y

orCFLAGS_.o

.

目标 all:

$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

:原型是make modules

,即是编译模块目标,其它都是参数

-C $(KERNEL_DIR)

:把工作目录跳转到内核源码中。

M=$(CURDIR)

:表示编译模块时,可以到该路径寻找模块源码进行编译。

推荐:观看内核文档Documentation/kbuild/modules.rst

3. 源码

# @file Makefile

# @brief 驱动。

# @details led 驱动模块 Makefile 例程。

# @author lzm

# @date 2021-03-14 10:23:03

# @version v1.1

# @copyright Copyright By lizhuming, All Rights Reserved

#

# ********************************************************

# @LOG 修改日志:

# ********************************************************

# 编译后内核路径

KERNEL_DIR = /home/lss/work/kernel/imx6/ebf-buster-linux/build_image/build

# 定义框架

# ARCH 为 x86 时,编译链头为

# ARCH 为 arm 时,编译链头为 arm-linux-gnueabihf-

ARCH = arm

ifeq ($(ARCH),x86)

CROSS_COMPILE = #

else

CROSS_COMPILE = arm-linux-gnueabihf-#

endif

CC = $(CROSS_COMPILE)gcc #

# 共享到sub-Makefile

export ARCH CROSS_COMPILE

# 路径

PWD := $(shell pwd)

MODDIR := $(src)

# 注意:驱动目标不要和文件名相同

TARGET_DRV := led_device_driver

TARGET_APP := led_app

# 本次整个编译需要源 文件 和 目录

$(TARGET_DRV)-y += led_module.o

$(TARGET_DRV)-y += ./device/led_dev_a.o

$(TARGET_DRV)-y += ./driver/led_drv.o

obj-m := $(TARGET_DRV).o

# obj-m += $(patsubst %.c,%.o,$(shell ls *.c))

# 编译条件处理

ccflags-y := -I$(MODDIR)/include

ccflags-y += -I$(MODDIR)/device

ccflags-y += -I$(MODDIR)/driver

# 第一个目标

all :

@$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

# $(CROSS_COMPILE)gcc -o $(TARGET_APP) $(TARGET_APP).c

# 清理

.PHONY:clean

clean:

$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean

# rm $(TARGET_APP)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值