linux(第十一期)--Makefile 语法简述-- Ubuntu20.04

变量赋值

复制代码
变量赋值
    - `VAR = value`:递归/延迟展开(在使用时再展开,适合引用其他变量)。
    - `VAR := value`:简单/立即展开(定义时就展开,效率高)。
    - `VAR ?= value`:条件赋值,只有变量未定义时才赋值(常用于默认值,如 `ARCH ?= arm`)。
    - `VAR += value`:追加(若变量未定义则等同于 `VAR = value`)。
    - `override VAR = value`:无视命令行/环境覆盖变量。
    - `export VAR` / `export VAR = value`:将变量导出到子 shell/命令。
    - `define NAME` ... `endef`:定义多行变量或宏体(可与 `$(call NAME, arg)` 一起使用)。

变量引用

复制代码
    - `$(VAR)` 或 `${VAR}`:引用变量值。注意两者等价,推荐 `$(VAR)`。
    - 延迟展开会在实际使用时才替换变量,立即展开则在赋值时替换。

规则

复制代码
- 语法:
     
    - recipe 行必须以 Tab 字符开头。
    - `.PHONY: clean all`:声明伪目标(不对应实际文件)。
    - 双冒号规则 `target:: ...`:允许多个独立配方(不常用)。
    - order-only 依赖:`target: normal_deps | order_only_deps`,`order_only_deps` 的变化不会触发重建,仅保证存在顺序。
    示例:
        hello.o: hello.c hello.h
      	$(CC) -c $< -o $@

    规则头 hello.o: hello.c hello.h

    目标(target)是 hello.o,依赖(prerequisites)是 hello.c 和 hello.h。
    含义:若 hello.o 不存在,或 hello.c/hello.h 比 hello.o 新,make 就会执行配方重建 hello.o。
    配方 $(CC) -c $< -o $@ 的含义:

    $(CC):使用的编译器(如 gcc,由变量 CC 指定)。
    -c:只编译,不链接,生成目标文件(.o)。
    $<:自动变量,表示第一个依赖,即 hello.c。
    $@:自动变量,表示目标,即 hello.o。
    整句就是把 hello.c 编译成 hello.o:相当于 gcc -c hello.c -o hello.o。

模式规则 / 隐式规则

复制代码
 示例: %.o: %.c
      	$(CC) $(CFLAGS) -c $< -o $@

规则头 %.o: %.c
表示一个模式规则:对任意同名的文件对,匹配 "源.c -> 目标.o" 的转换(例如 foo.c -> foo.o)。

配方 $(CC) $(CFLAGS) -c $< -o $@ 含义:

$(CC):编译器(如 gcc)。
$(CFLAGS):编译选项。
-c:只编译成目标文件,不链接。
$<:自动变量,表示第一个依赖(这里是 foo.c)。
$@:自动变量,表示目标(这里是 foo.o)。
所以整句相当于:把源文件编译成对应的目标文件(例:gcc -c foo.c -o foo.o)。

自动变量(常用)

复制代码
    - `$@`:规则的目标文件名。
    - `$<`:第一个依赖(常用于模式规则)。
    - `$^`:所有依赖(去重)。
    - `$?`:比目标新的依赖列表(用于增量处理)。

条件判断与控制

复制代码
    - `ifeq (a,b)` / `ifneq`:字符串比较(注意空格和引号)。
    - `ifdef VAR` / `ifndef VAR`:判断变量是否定义。
    - `else` / `endif`:配套使用。条件常用于根据 `ARCH`、`CROSS_COMPILE` 等切换行为。

包含与容错包含

复制代码
     `include filename`:包含其它 Makefile 片段(例如自动生成的依赖文件)。
     `-include filename` 或 `sinclude filename`:若文件不存在则忽略,不报错。

函数与内建处理

复制代码
    文本/列表函数:`$(subst from,to,text)`、`$(patsubst pattern,repl,text)`、`$(filter pattern...,text)`、`$(filter-out ...)`。
     文件/目录函数:`$(wildcard pattern)`、`$(dir list)`、`$(notdir list)`。
     迭代与调用:`$(foreach var, list, text)`、`$(call macro, args...)`(配合 `define` 使用)。
    `$(shell cmd)`:执行 shell 命令并将输出作为字符串返回(慎用,频繁调用影响性能)。

目标特定变量与模式特定变量

复制代码
  目标特定:`foo.o: CFLAGS = -O2`(仅对 `foo.o` 有效)。
  模式特定:`%.o: CFLAGS = -g`(对匹配规则的目标生效)。

调试与诊断

复制代码
   `make -n`:只显示将执行的命令,不运行。
     `make -p`:打印数据库(变量、规则等)。
     `make -d`:详细调试输出(非常冗长)。
     工程常用 `V=1`、`V=2` 等变量切换命令行详细程度(这是项目约定,不是 GNU make 固有)。

常见约定(U-Boot 风格)

复制代码
     使用 `ARCH`、`CROSS_COMPILE`、`O`(输出目录)、`KBUILD_*` 等变量控制构建。
     先构建 host-tools(如 `tools/mkimage`),再构建目标代码。
     使用 `if_changed`、`cmd_*`、`quiet_cmd_*` 等宏实现"只在命令变化时执行"的机制,减少不必要重建。
     提供 `make <board>_defconfig`、`make menuconfig`、`make u-boot.bin` 等目标,结合 `configs/` 和 `include/configs/` 管理配置。
相关推荐
博语小屋2 小时前
设计一个简单的网络计算器并将其守护进程化
linux·网络·tcp/ip
星火开发设计2 小时前
枚举类 enum class:强类型枚举的优势
linux·开发语言·c++·学习·算法·知识
喜欢吃燃面7 小时前
Linux:环境变量
linux·开发语言·学习
佑白雪乐10 小时前
<Linux基础第10集>复习前面内容
linux·运维·服务器
春日见10 小时前
自动驾驶规划控制决策知识点扫盲
linux·运维·服务器·人工智能·机器学习·自动驾驶
暮云星影10 小时前
四、linux系统 应用开发:UI开发环境配置概述 (三)
linux·ui·arm
迷途知返-11 小时前
服务器——那些年我踩过的坑
linux
landonVM12 小时前
Linux 上搭建 Web 服务器
linux·服务器·前端
云游云记12 小时前
nesbot/carbon 常用功能总结
linux·运维·服务器
慵懒的猫mi12 小时前
从XDG正式支持如意玲珑(Linyaps)看如意玲珑的发展与架构演进
linux·开源软件·deepin