• Makefile 中一些常用语法讲解


     解释下面makefile内容的意思

    1. # Common part--------------------------------------------------------------------
    2. DRV_NAME := xxx
    3. DRV_PATH := xxxxx
    4. # KBuild part of makefile--------------------------------------------------------
    5. ifneq ($(KERNELRELEASE),)
    6. obj-m := $(DRV_NAME).o
    7. $(DRV_NAME)-objs += can_init.o
    8. $(DRV_NAME)-objs += sja1000/sja1000.o
    9. $(DRV_NAME)-objs += AAAA/AAAA.o
    10. EXTRA_CFLAGS += -std=gnu99
    11. # Normal makefile----------------------------------------------------------------
    12. else
    13. KVER := $(shell uname -r)
    14. KSRC ?= /lib/modules/$(KVER)/build
    15. KMOD ?= /lib/modules/$(KVER)/kernel/drivers/$(DRV_PATH)
    16. all:
    17. $(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 的情况下通过命令行参数动态地修改变量的值。例如:

    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

    KDIR := /usr/src/linux-headers-$(shell uname -r)
    

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

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

    1. all:
    2. $(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 命令可以动态地加载指定的内核模块到系统中,使其成为可用的内核功能。加载模块通常会触发相应的硬件初始化或功能启动。

      modprobe module_name

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

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

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

      modprobe -r module_name

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

      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 命令将其卸载。这样的操作通常用于确保在重新安装或编译时,先卸载已加载的模块,以便重新加载新的模块。

  • 相关阅读:
    minio双机部署
    C语言找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点
    前端面试html自检(先看问题 自己自述一遍 不会再看答案 )
    [Vite]import.meta.glob批量引入svg图片
    使用SwinUnet训练自己的数据集
    垃圾回收器
    zfaka 虎皮椒微信+支付宝插件(内附说明)
    ChatGPT辅助下的小组学习
    微信小程序 java健康评估系统springboot
    LuatOS-SOC接口文档(air780E)--mqtt - mqtt客户端
  • 原文地址:https://blog.csdn.net/Wang_anna/article/details/133746233