[make] - Makefile 中,Recipe(规则体)是指什么

 

A simple makefile consists of “rules” with the following shape:

`

target ... : prerequisites ...
recipe
...
...

`

A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as ‘clean’ (see Section 4.5 [Phony Targets], page 31).
A prerequisite is a file that is used as input to create the target. A target often depends on several files.
A recipe is an action that make carries out. A recipe may have more than one command, either on the same line or each on its own line. Please note: you need to put a tab character at the beginning of every recipe line! This is an obscurity that catches the unwary.
If you prefer to prefix your recipes with a character other than tab, you can set the .RECIPEPREFIX variable to an alternate character (see Section 6.14 [Special Variables], page 80).

 

 

A recipe is an action that make carries out. A recipe may have more than one command, either on the same line or each on its own line.

(Please note: you need to put a tab character at the beginning of every recipe line! This is an obscurity that catches the unwary. If you prefer to prefx your recipes with a character other than tab, you can set the .RECIPEPREFIX variable to an alternate character (see Section 6.14 [Special Variables], page 80).)

Usually a recipe is in a rule with prerequisites and serves to create a target fle if any of the prerequisites change. However, the rule that specifes a recipe for the target need not have prerequisites. For example, the rule containing the delete command associated with the target ‘clean’ does not have prerequisites.

A rule, then, explains how and when to remake certain fles which are the targets of the particular rule. make carries out the recipe on the prerequisites to create or update the target. A rule can also explain how and when to carry out an action. See Chapter 4 [Writing Rules], page 23.

A makefle may contain other text besides rules, but a simple makefle need only contain rules. Rules may look somewhat more complicated than shown in this template, but all fit the pattern more or less.

 

在 Makefile 中,Recipe(规则体)​ 是规则(Rule)中定义如何生成目标(Target)的具体操作步骤,通常由一系列 Shell 命令​ 组成。其核心作用是描述 依赖文件更新后需要执行的构建动作


1. Recipe 的基本语法

  • 格式

    target: prerequisites
        command1  # 以 Tab 缩进
        command2
  • 关键特性

    • 缩进要求:每行命令必须以 Tab 字符​ 开头(不能用空格替代) 

    • Shell 解释:命令由 Shell 执行(如 Bash),支持管道、变量替换等 Shell 语法 

    • 隐式规则:若未显式定义命令,Make 会尝试使用内置规则(如 .c → .o) 


2. Recipe 的作用

  • 编译代码:例如将 .c文件编译为 .o文件:

    main.o: main.c
        gcc -c main.c -o main.o
  • 链接程序:将多个 .o文件合并为可执行文件:

    myapp: main.o utils.o
        gcc main.o utils.o -o myapp
  • 清理操作:删除中间文件:

     
    clean:
        rm -f *.o myapp

3. Recipe 的高级特性

(1) 自动化变量

  • $@:当前目标名称。

  • $<:第一个依赖文件。

  • $^:所有依赖文件(去重后)。

  • $?:比目标更新的依赖文件列表。

示例:

makefile
复制
 
 
%.o: %.c
    $(CC) -c $< -o $@  # 使用 $< 代替第一个依赖文件

(2) 条件执行

  • 忽略错误:在命令前加 -,即使命令失败也继续执行:

     
    clean:
        -rm -f non_existent_file
  • 静默模式:用 @抑制命令回显:

    all:
        @echo "Building project..."

(3) 多行命令

使用 ``换行符分割多行命令:

complex_task:
    echo "Step 1"; \
    mkdir build; \
    cd build && make

4. 示例:完整 Makefile

CC = gcc
CFLAGS = -Wall -O2
SRCS = main.c utils.c
OBJS = $(SRCS:.c=.o)
TARGET = myapp

.PHONY: all clean

all: $(TARGET)

$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) $^ -o $@

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f $(OBJS) $(TARGET)

5. 常见问题与最佳实践

  • 缩进错误:确保命令前是 Tab 而非空格(可通过 cat -A检查) 

  • 变量展开:在规则上下文中定义的变量会被 Shell 解释,而非 Make 处理 

  • 依赖管理:显式声明所有依赖,避免因遗漏导致构建错误 


总结

Makefile 的 Recipe​ 是构建逻辑的核心,通过 Shell 命令​ 实现从依赖到目标的转换。合理使用自动化变量、条件判断和隐式规则,可显著提升 Makefile 的灵活性和可维护性。

posted on 2025-11-28 14:47  ENGINEER-F  阅读(0)  评论(0)    收藏  举报