Makefile 中一些常用语法讲解

解释下面makefile内容的意思

bash 复制代码
# Common part--------------------------------------------------------------------
DRV_NAME := xxx
DRV_PATH := xxxxx

# KBuild part of makefile--------------------------------------------------------
ifneq ($(KERNELRELEASE),)

obj-m := $(DRV_NAME).o
$(DRV_NAME)-objs += can_init.o
$(DRV_NAME)-objs += sja1000/sja1000.o
$(DRV_NAME)-objs += AAAA/AAAA.o

EXTRA_CFLAGS += -std=gnu99

# Normal makefile----------------------------------------------------------------
else

KVER := $(shell uname -r)
KSRC ?= /lib/modules/$(KVER)/build
KMOD ?= /lib/modules/$(KVER)/kernel/drivers/$(DRV_PATH)

all:	
	$(MAKE) -w -C $(KSRC) M=$(PWD) modules

这是一个 Linux 内核模块的 Makefile,用于构建一个名为 $(DRV_NAME) 的内核模块。让我解释一下每个部分的含义:

  • ifneq ($(KERNELRELEASE),):这是一个条件语句,检查是否在内核构建阶段。如果 KERNELRELEASE 已定义,说明是在内核构建阶段,将执行下面的代码。
  • obj-m := $(DRV_NAME).o:定义了要构建的内核模块的目标文件。
  • $(DRV_NAME)-objs += ...:指定模块的源文件。这里包括 can_init.osja1000/sja1000.oAAAA/AAAA.o
  • EXTRA_CFLAGS += -std=gnu99:指定编译模块时要使用的额外编译标志,这里是将 C 语言标准设置为 GNU99。
  • else:如果不在内核构建阶段,执行下面的代码。
    • KVER := $(shell uname -r):获取当前系统的内核版本。
    • KSRC ?= /lib/modules/$(KVER)/build:指定内核源代码的路径,默认为 /lib/modules/$(KVER)/build
    • KMOD ?= /lib/modules/$(KVER)/kernel/drivers/$(DRV_PATH):指定模块要安装的位置,默认为 /lib/modules/$(KVER)/kernel/drivers/$(DRV_PATH)
    • all::定义了一个名为 "all" 的目标,该目标将在执行 make 命令时被调用。
    • $(MAKE) -w -C $(KSRC) M=$(PWD) modules:这是实际构建模块的命令。它告诉 make 到内核源代码路径 $(KSRC) 下执行构建,并使用当前目录 $(PWD) 中的 Makefile。最终目标是构建内核模块。
  • 这个 Makefile 的目的是构建一个名为 $(DRV_NAME) 的内核模块,包括指定的源文件。在构建阶段,它会使用指定的内核源代码路径进行编译。

KMOD ?=xxx的作用是?

在给定的 Makefile 中,KMOD ?= xxx 的作用是定义一个变量 KMOD,并为其设置默认值为 xxx。这样的语法通常被用于为变量提供默认值,但允许在执行 make 命令时通过命令行参数进行覆盖。

具体来说:

  • KMOD ?= /lib/modules/$(KVER)/kernel/drivers/$(DRV_PATH) 设置了变量 KMOD 的默认值。
  • 如果在执行 make 命令时未提供对 KMOD 的显式赋值,它将采用默认值。
  • 如果你在执行 make 命令时通过命令行为 KMOD 赋值,那么该命令行上的值将覆盖默认值。

这样做的好处是,它允许用户在不修改 Makefile 的情况下通过命令行参数动态地修改变量的值。例如:

bash 复制代码
make KMOD=/path/to/custom/directory

在上述命令中,KMOD 将被设置为 /path/to/custom/directory,而不是默认值。

KDIR := xxx的作用?

在 Linux 内核模块的 Makefile 中,KDIR := xxx 用于指定内核源代码的路径。通常,这是为了告诉 make 在哪里可以找到内核源代码以便编译内核模块。

具体来说:

  • KDIR 是一个变量,用于存储内核源代码的路径。
  • := 是 Makefile 中的赋值运算符,表示立即展开,即在执行 make 时,xxx 的值就被赋给 KDIR
  • xxx 应该是一个包含内核源代码的路径。

举例来说,如果内核源代码位于 /usr/src/linux-headers-$(shell uname -r),你可以在 Makefile 中这样设置 KDIR

bash 复制代码
KDIR := /usr/src/linux-headers-$(shell uname -r)

这个路径是一个常见的默认路径,通常包含与当前运行的内核版本匹配的头文件和配置信息。

然后,在 Makefile 中,你可以使用 KDIR 变量来指定内核源代码的位置,比如在编译内核模块时:

bash 复制代码
all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

上述命令告诉 make 在指定的内核源代码路径中进行编译,使用当前目录 ($(PWD)) 中的 Makefile 编译内核模块。这样可以确保内核模块编译使用了正确版本的头文件和配置。

can_dev 2>/dev/null 这个是什么意思?

这是一个 shell 命令,用于运行名为 can_dev 的可执行文件,并将标准错误流(stderr)重定向到 /dev/null

具体来说:

  • 2> 表示将标准错误流重定向。
  • /dev/null 是一个特殊的设备文件,用于丢弃数据。在这里,它用作标准错误流的目标,即将错误信息输出到空设备,从而将其消除。

整体来说,这个命令的目的是在运行 can_dev 可执行文件时,忽略掉任何可能产生的错误消息,将错误信息丢弃到 /dev/null 中,而不在终端或日志中显示。这种做法通常用于在脚本中执行命令时,希望保持输出干净,不受错误消息的干扰。

modprobe的作用?

modprobe 是 Linux 系统中用于加载和卸载内核模块的命令。它的作用包括:

  1. 加载内核模块: 使用 modprobe 命令可以动态地加载指定的内核模块到系统中,使其成为可用的内核功能。加载模块通常会触发相应的硬件初始化或功能启动。

    bash 复制代码
    modprobe module_name

    例如,如果要加载名为 my_module 的内核模块,可以运行:

    bash 复制代码
    modprobe my_module
  2. 自动解决依赖关系: modprobe 会自动解决并加载指定模块所依赖的其他模块,确保加载过程中所有依赖关系都被满足。

  3. 卸载内核模块: 除了加载,modprobe 也可以用于卸载已加载的内核模块。

    bash 复制代码
    modprobe -r module_name

    例如,要卸载名为 my_module 的内核模块,可以运行:

    bash 复制代码
    modprobe -r my_module
  4. 配置文件查找: modprobe 还会查找配置文件,如 /etc/modprobe.conf/etc/modprobe.d/*,以获取有关模块加载和相关设置的额外信息。

总体而言,modprobe 提供了一个方便的命令行界面,用于管理系统中的内核模块。

(shell ! \[ -d (KMOD) ] && mkdir $(KMOD))

这个是啥意思?

这是一个在 Makefile 中使用的 GNU Make 扩展语法,用于检查目录是否存在,如果不存在则创建目录。

让我们解释一下这个命令:

  • $(shell ...) 是 GNU Make 中用于执行 shell 命令的函数。
  • ! [ -d $(KMOD) ] 是一个 shell 条件语句,用于检查 $(KMOD) 是否为一个目录。
    • -d $(KMOD) 检查目录是否存在。
    • ! [ ... ] 表示逻辑取反,即如果目录不存在,则条件为真。
  • mkdir $(KMOD) 用于创建目录 $(KMOD)

因此,整个命令的意思是,如果目录 $(KMOD) 不存在,则创建它。这种技巧通常用于确保在编译或安装过程中某个目录存在,以避免后续操作出现错误。

(shell cp -f ./(DRV_NAME).ko (KMOD)/ \&\& depmod \&\& modprobe (DRV_NAME))

这个是啥意思?

这是一个在 Makefile 中使用的 GNU Make 扩展语法,用于执行一系列 shell 命令。让我们逐步解释这个命令:

  1. $(shell ...) 是 GNU Make 中用于执行 shell 命令的函数。

  2. cp -f ./$(DRV_NAME).ko $(KMOD)/:这个命令使用 cp 命令将当前目录下的 $(DRV_NAME).ko 文件复制到目标目录 $(KMOD),并使用 -f 选项强制覆盖目标目录中的同名文件。

  3. depmod:这个命令用于生成模块依赖关系,通常在安装新的内核模块后运行,以确保内核正确识别和加载模块。

  4. modprobe $(DRV_NAME):这个命令用于加载指定的内核模块,其中 $(DRV_NAME) 是模块的名称。

因此,整个命令的意思是,在执行 make 命令时:

  • 将当前目录下的 $(DRV_NAME).ko 文件复制到目标目录 $(KMOD)
  • 运行 depmod 以更新模块依赖关系。
  • 运行 modprobe $(DRV_NAME) 以加载新的内核模块。

这样的命令通常用于在安装或编译过程中自动安装和加载内核模块。

$(shell if grep advsocketcan /proc/modules > /dev/null ; then \ rmmod advsocketcan; fi)

这的意思?

这是一个在 Makefile 中使用的 GNU Make 扩展语法,用于执行一系列 shell 命令。让我们逐步解释这个命令:

  • $(shell ...) 是 GNU Make 中用于执行 shell 命令的函数。

  • if grep advsocketcan /proc/modules > /dev/null ; then rmmod advsocketcan; fi 是一个 shell 条件语句,它的作用是:

    • grep advsocketcan /proc/modules 用于检查 /proc/modules 文件中是否包含字符串 "advsocketcan"。这个文件列出了当前加载的内核模块。

    • > /dev/null 是将输出重定向到 /dev/null,即丢弃输出,不显示在终端上。

    • 如果 grep 命令成功找到了 "advsocketcan" 字符串,条件为真,那么 then 后面的命令 rmmod advsocketcan 将卸载名为 "advsocketcan" 的内核模块。

整个命令的目的是在执行 make 命令时,检查系统中是否已经加载了名为 "advsocketcan" 的内核模块,如果已经加载,则使用 rmmod 命令将其卸载。这样的操作通常用于确保在重新安装或编译时,先卸载已加载的模块,以便重新加载新的模块。

相关推荐
ximy133512 分钟前
AI服务器工作之服务器的种类分类
运维·服务器
恒创科技HK15 分钟前
香港服务器CPU中E5和Gold的区别
运维·服务器
黄沐阳1 小时前
stp,rstp,mstp的区别
服务器·网络·php
一张假钞2 小时前
Ubuntu SSH 免密码登陆
linux·ubuntu·ssh
清静诗意2 小时前
在 Ubuntu 上安装 MinIO 并使用 Python 封装类操作对象存储
服务器·minio
Wang's Blog3 小时前
Linux小课堂: 文件操作警惕高危删除命令与深入文件链接机制
linux·运维·服务器
水月wwww4 小时前
操作系统——进程管理
linux·操作系统·vim·进程·进程调度
2501_915909064 小时前
iOS 混淆实战,多工具组合完成 IPA 混淆与加固(源码 + 成品 + 运维一体化方案)
android·运维·ios·小程序·uni-app·iphone·webview
我科绝伦(Huanhuan Zhou)4 小时前
分享一个可以一键制作在线yum源的脚本
linux·运维
爱宇阳5 小时前
禅道社区版 Docker Compose 服务迁移教程
运维·docker·容器