GNU Make 用户手册(中文版)

GNU Make 4.4.1 官方手册(Edition 0.77, 2023年2月26日更新)

原文:https://www.gnu.org/software/make/manual/


目录

  1. 概述
  2. [Makefile 入门](#Makefile 入门)
  3. [编写 Makefile](#编写 Makefile)
  4. 编写规则
  5. 编写配方
  6. 使用变量
  7. 条件判断
  8. 文本变换函数
  9. [运行 make](#运行 make)
  10. 隐式规则
  11. 附录:快速参考

1. 概述

1.1 什么是 Make

make 是一个自动构建工具,它能够自动确定大型程序中哪些部分需要重新编译,并执行相应的命令来完成编译。GNU make 由 Richard Stallman 和 Roland McGrath 实现,3.76 版本之后由 Paul D. Smith 维护。

GNU make 遵循 IEEE 标准 1003.2-1992 (POSIX.2) 第 6.2 节。

虽然本文示例使用 C 语言,但 make 适用于任何可以通过 shell 命令运行编译器的编程语言。实际上,make 不限于程序编译------它可以描述任何需要根据文件变化自动更新其他文件的任务。

1.2 如何阅读本手册

  • 如果你对 make 完全陌生,从第 2 章开始阅读
  • 如果你有经验,可以直接跳到相关章节
  • 附录 A 提供了快速参考

2. Makefile 入门

2.1 规则长什么样

一个简单的 makefile 由"规则"组成,格式如下:

makefile 复制代码
目标 ... : 前置条件 ...
    配方
    ...
  • 目标(target) :通常是程序生成的文件名(如可执行文件或目标文件),也可以是某个动作的名称(如 clean
  • 前置条件(prerequisite):作为输入来创建目标的文件
  • 配方(recipe) :make 执行的动作。注意:每个配方行必须以 Tab 字符开头!

2.2 一个简单的 Makefile 示例

以下 makefile 描述了一个名为 edit 的可执行文件如何依赖于 8 个目标文件,而这些目标文件又依赖于 8 个 C 源文件和 3 个头文件:

makefile 复制代码
edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
    cc -o edit main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o

使用方式:

  • make --- 构建可执行文件 edit
  • make clean --- 删除所有编译产物

2.3 Make 如何处理 Makefile

默认情况下,make 从第一个目标(称为默认目标)开始处理:

  1. 读取当前目录的 makefile
  2. 处理第一个规则(通常是链接可执行文件)
  3. 在处理第一个规则之前,先处理其所有前置条件的规则
  4. 对于每个 .o 文件,检查源文件和头文件是否比目标文件更新
  5. 如果任何前置条件更新了,则重新编译
  6. 最后,如果任何目标文件被重新编译,则重新链接可执行文件

2.4 使用变量简化 Makefile

使用变量可以避免重复列出文件:

makefile 复制代码
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
    cc -o edit $(objects)

main.o : main.c defs.h
    cc -c main.c
# ... 其他规则类似
clean :
    rm edit $(objects)

3. 编写 Makefile

3.1 Makefile 包含的内容

Makefile 包含五种内容:

  1. 显式规则 --- 说明何时以及如何重新生成一个或多个文件
  2. 隐式规则 --- 根据文件名自动推断如何重新生成一类文件
  3. 变量定义 --- 为变量指定文本字符串值
  4. 指令 --- 让 make 在读取 makefile 时做特殊处理(如包含其他 makefile、条件判断、定义多行变量)
  5. 注释 --- 以 # 开头

3.2 Makefile 的命名

make 按以下顺序查找 makefile:

  1. GNUmakefile
  2. makefile
  3. Makefile

推荐使用 MakefileGNUmakefile 只在你的 makefile 特定于 GNU make 时使用。

使用 -f 选项可以指定其他文件名:

bash 复制代码
make -f mymakefile

3.3 包含其他 Makefile

makefile 复制代码
include filenames...
  • 支持通配符
  • 搜索路径:-I 选项指定的目录 → /usr/local/include/usr/include
  • -includesinclude 在文件不存在时不会报错

示例:

makefile 复制代码
include foo *.mk $(bar)

3.4 拆分长行

使用反斜杠加换行符来拆分长行:

makefile 复制代码
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

4. 编写规则

4.1 规则语法

makefile 复制代码
目标 : 前置条件
    配方
  • 规则顺序不重要,除非是确定默认目标
  • 默认目标是第一个 makefile 中第一个规则的目标
  • . 开头的目标不作为默认目标(除非包含 /

4.2 前置条件的类型

GNU make 支持两种前置条件:

  • 普通前置条件:如果比目标新,则触发重新构建
  • 仅顺序前置条件(order-only) :用 | 分隔,仅确保它们存在,不触发重新构建
makefile 复制代码
目标 : 普通前置条件 | 仅顺序前置条件

4.3 通配符

支持 shell 风格的通配符:*?[...]

makefile 复制代码
clean:
    rm -f *.o

注意 :通配符在目标和前置条件中自动展开,在配方中由 shell 展开,在其他上下文中需要使用 $(wildcard ...) 函数。

~ 表示家目录:~/bin~john/bin

4.4 目录搜索(VPATH)

使用 VPATH 变量或 vpath 指令来搜索前置条件:

makefile 复制代码
VPATH = src:../headers

或更精确的:

makefile 复制代码
vpath %.c src
vpath %.h ../headers

4.5 伪目标(Phony Targets)

伪目标不是文件名,而是动作的名称。使用 .PHONY 声明:

makefile 复制代码
.PHONY: clean
clean:
    rm -f *.o

常见用法:

  • all --- 构建所有程序
  • clean --- 清理
  • 递归调用子目录 make

4.6 静态模式规则

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

4.7 双冒号规则

双冒号规则允许同一个目标有多个规则,每个规则有自己的配方:

makefile 复制代码
目标 :: 前置条件
    配方

4.8 自动生成前置条件

使用编译器的 -M 选项自动生成依赖关系:

makefile 复制代码
%.d: %.c
    @set -e; rm -f $@; \
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

然后包含生成的 .d 文件:

makefile 复制代码
sources = foo.c bar.c
include $(sources:.c=.d)

5. 编写配方

5.1 配方语法

配方由一行或多行 shell 命令组成,每行必须以 Tab 开头(或 .RECIPEPREFIX 指定的字符)。

5.2 配方回显

  • 默认情况下,make 在执行前打印每行命令
  • 在命令前加 @ 可以禁止回显:@echo "Building..."

5.3 配方执行

  • 每行配方在独立的 shell 进程中执行
  • 可以使用 .ONESHELL 让所有行在同一个 shell 中执行
  • 可以通过 SHELL 变量指定 shell

5.4 并行执行

使用 -j 选项:

bash 复制代码
make -j4          # 同时执行 4 个任务
make -j           # 不限数量的并行任务
make -l 2.5       # 负载平均值超过 2.5 时不启动新任务

5.5 配方错误处理

  • 在命令前加 - 忽略错误:-rm -f *.o
  • -i--ignore-errors 忽略所有错误
  • -k--keep-going 出错后继续构建其他目标
  • .DELETE_ON_ERROR 让 make 在配方失败时删除目标文件

5.6 递归使用 Make

在子目录中调用 make:

makefile 复制代码
subsystem:
    cd subdir && $(MAKE)

或:

makefile 复制代码
subsystem:
    $(MAKE) -C subdir

重要 :始终使用 $(MAKE) 而非 make,这样能正确传递标志和变量。

5.7 定义罐头配方

使用 define 定义可重用的配方:

makefile 复制代码
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef

foo.c: foo.y
    $(run-yacc)

6. 使用变量

6.1 变量引用基础

使用 $(变量名)${变量名} 引用变量:

makefile 复制代码
objects = program.o foo.o utils.o
program : $(objects)
    cc -o program $(objects)
  • 变量名区分大小写:fooFOOFoo 是不同的变量
  • 单字符变量可以省略括号:$x,但推荐使用括号
  • $$ 表示一个字面量 $

6.2 变量的两种风格

6.2.1 递归展开变量(=

值在每次使用时才展开:

makefile 复制代码
foo = $(bar)
bar = $(ugh)
ugh = Huh?
# $(foo) 最终展开为 "Huh?"

优点:可以后定义引用的变量

缺点:不能追加自身(会导致无限循环),函数每次使用时都会重新执行

6.2.2 简单展开变量(:=::=

值在定义时立即展开:

makefile 复制代码
x := foo
y := $(x) bar
x := later
# y 的值是 "foo bar"(定义时的值)

优点:可预测,性能好,可以追加自身

6.2.3 立即展开变量(:::=

立即展开但结果是递归变量(值中的 $ 被转义为 $$):

makefile 复制代码
var = first
OUT :::= $(var)
var = second
# OUT 的值是 "first",但作为递归变量
6.2.4 条件赋值(?=

只在变量未定义时赋值:

makefile 复制代码
FOO ?= bar
# 等价于:
ifeq ($(origin FOO), undefined)
FOO = bar
endif

6.3 设置变量

makefile 复制代码
# 递归展开
变量 = 值

# 简单展开
变量 := 值

# 立即展开(递归结果)
变量 :::= 值

# 条件赋值
变量 ?= 值

# 追加
变量 += 值

6.4 追加文本

makefile 复制代码
objects = main.o
objects += foo.o
# objects 现在是 "main.o foo.o"

6.5 Override 指令

覆盖命令行传入的变量:

makefile 复制代码
override CFLAGS += -g

6.6 多行变量

makefile 复制代码
define two-lines
echo foo
echo $(bar)
endef

6.7 环境变量

  • make 启动时自动导入环境变量
  • 可以使用 -e 选项让环境变量覆盖 makefile 中的变量
  • 使用 export 将变量传递给子进程

6.8 目标特定变量

makefile 复制代码
prog : CFLAGS = -g
prog : prog.o foo.o
    $(CC) $(CFLAGS) -o prog prog.o foo.o

6.9 模式特定变量

makefile 复制代码
%.o : CFLAGS = -O2

6.10 自动变量

在配方中使用的特殊变量,由 make 自动设置:

变量 含义
$@ 目标文件名
$% 归档成员名(当目标是归档文件时)
$< 第一个前置条件
$? 所有比目标新的前置条件
$^ 所有前置条件(去重)
$+ 所有前置条件(不去重)
`$ `
$* 模式规则匹配的"茎"(stem)

目录变体(追加 DF):

  • $(@D) --- 目标的目录部分
  • $(@F) --- 目标的文件名部分
  • $(<D) --- 第一个前置条件的目录部分
  • $(<F) --- 第一个前置条件的文件名部分
  • 以此类推:$(*D)$(*F)$(^D)$(^F)$(?D)$(?F)

7. 条件判断

7.1 条件示例

makefile 复制代码
ifeq ($(CC),gcc)
    $(CC) -o foo $(objects) $(libs_for_gcc)
else
    $(CC) -o foo $(objects) $(normal_libs)
endif

7.2 条件语法

makefile 复制代码
conditional-directive
    text-if-true
else
    text-if-false
endif

支持的指令:

指令 说明
ifeq (arg1, arg2) 如果相等则为真
ifneq (arg1, arg2) 如果不相等则为真
ifdef variable-name 如果变量已定义(非空)则为真
ifndef variable-name 如果变量未定义(为空)则为真

注意ifdef 只检查变量是否被定义,不展开变量值。foo = 被认为是空,但 foo = $(bar) 即使 bar 为空也被认为是已定义。

7.3 测试标志

makefile 复制代码
ifeq ($(findstring clean,$(MAKECMDGOALS)),clean)
    # 如果目标是 clean
endif

8. 文本变换函数

8.1 函数调用语法

makefile 复制代码
$(函数名 参数1,参数2,...)
${函数名 参数1,参数2,...}

8.2 字符串替换和分析函数

$(subst from,to,text)

替换文本中的子串:

makefile 复制代码
$(subst ee,EE,feet on the street)
# 结果:fEEt on the strEEt
$(patsubst pattern,replacement,text)

模式替换(% 通配):

makefile 复制代码
$(patsubst %.c,%.o,x.c.c bar.c)
# 结果:x.c.o bar.o

替换引用(简化写法):

makefile 复制代码
$(var:.o=.c)           # 等价于 $(patsubst %.o,%.c,$(var))
$(var:pattern=replacement)  # 等价于 $(patsubst pattern,replacement,$(var))
$(strip string)

去除首尾空白,合并内部空白:

makefile 复制代码
$(strip a b c )
# 结果:a b c
$(findstring find,in)

查找子串:

makefile 复制代码
$(findstring a,a b c)  # 结果:a
$(findstring a,b c)    # 结果:(空)
$(filter pattern...,text)

筛选匹配模式的单词:

makefile 复制代码
sources := foo.c bar.c baz.s ugh.h
$(filter %.c %.s,$(sources))
# 结果:foo.c bar.c baz.s
$(filter-out pattern...,text)

筛选不匹配模式的单词:

makefile 复制代码
$(filter-out $(mains),$(objects))
$(sort list)

排序并去重:

makefile 复制代码
$(sort foo bar lose)
# 结果:bar foo lose
$(word n,text)

取第 n 个单词(从 1 开始):

makefile 复制代码
$(word 2, foo bar baz)
# 结果:bar
$(wordlist s,e,text)

取单词范围:

makefile 复制代码
$(wordlist 2, 3, foo bar baz)
# 结果:bar baz
$(words text)

单词计数:

makefile 复制代码
$(words foo bar baz)
# 结果:3
$(firstword names...)

取第一个单词:

makefile 复制代码
$(firstword foo bar)
# 结果:foo
$(lastword names...)

取最后一个单词:

makefile 复制代码
$(lastword foo bar)
# 结果:bar

8.3 文件名函数

$(dir names...)

提取目录部分:

makefile 复制代码
$(dir src/foo.c hacks)
# 结果:src/ ./
$(notdir names...)

提取文件名部分:

makefile 复制代码
$(notdir src/foo.c hacks)
# 结果:foo.c hacks
$(suffix names...)

提取后缀:

makefile 复制代码
$(suffix src/foo.c src-1.0/bar.c hacks)
# 结果:.c .c
$(basename names...)

提取基本名(去掉后缀):

makefile 复制代码
$(basename src/foo.c src-1.0/bar hacks)
# 结果:src/foo src-1.0/bar hacks
$(addsuffix suffix,names...)

添加后缀:

makefile 复制代码
$(addsuffix .c,foo bar)
# 结果:foo.c bar.c
$(addprefix prefix,names...)

添加前缀:

makefile 复制代码
$(addprefix src/,foo bar)
# 结果:src/foo src/bar
$(join list1,list2)

连接两个列表(逐词):

makefile 复制代码
$(join a b,.c .o)
# 结果:a.c b.o
$(wildcard pattern)

通配符匹配(返回存在的文件):

makefile 复制代码
$(wildcard *.c)
$(realpath names...)

获取规范绝对路径(解析符号链接):

makefile 复制代码
$(realpath foo.c)
$(abspath names...)

获取绝对路径(不解析符号链接):

makefile 复制代码
$(abspath foo.c)

8.4 条件函数

$(if condition,then-part[,else-part])
makefile 复制代码
$(if $(wildcard foo.c),foo.c,)
$(or condition1[,condition2...])

返回第一个非空值。

$(and condition1[,condition2...])

如果所有条件都非空,返回最后一个条件的值。

$(intcmp lhs,rhs[,lt-part[,eq-part[,gt-part]]])

数值比较。

8.5 $(foreach var,list,text)

循环展开:

makefile 复制代码
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))

8.6 $(call var,param,...)

调用用户定义的函数:

makefile 复制代码
reverse = $(2) $(1)
foo = $(call reverse,a,b)
# foo 的值:b a

8.7 $(shell command)

执行 shell 命令并返回输出:

makefile 复制代码
contents := $(shell cat foo)
files := $(shell echo *.c)

8.8 $(error text...)$(warning text...)

makefile 复制代码
ifndef CONFIG_FILE
$(error CONFIG_FILE is not set)
endif

$(warning This is a warning)

8.9 $(origin variable)

返回变量来源的描述:

  • undefined --- 未定义
  • default --- 默认定义
  • environment --- 环境变量
  • file --- makefile 中定义
  • command line --- 命令行定义
  • override --- override 指令
  • automatic --- 自动变量
  • makefile --- makefile 中定义

8.10 $(eval text)

将文本作为 makefile 语法求值:

makefile 复制代码
$(eval $(call program-variable,foo))

9. 运行 Make

9.1 指定 Makefile

bash 复制代码
make -f mymakefile
make --file=mymakefile

9.2 指定目标

bash 复制代码
make clean          # 构建 clean 目标
make all install    # 构建 all 和 install

9.3 替代执行

bash 复制代码
make -n             # 只打印命令,不执行(dry-run)
make -t             # touch 目标文件
make -q             # 检查是否过时(不执行)

9.4 避免重新编译

bash 复制代码
make -o main.o      # 假装 main.o 没有过时

9.5 覆盖变量

bash 复制代码
make CFLAGS="-O2 -g"
make CC=gcc-12

9.6 选项汇总

选项 说明
-B, --always-make 无条件重新构建所有目标
-C dir 切换到目录 dir
-d 打印调试信息
--debug[=选项] 调试选项:a(全部), b(基本), v(详细), i(隐式规则), j(作业), m(makefile), p(打印配方), w(原因)
-e 环境变量覆盖 makefile 变量
-f file 指定 makefile
-i 忽略所有错误
-I dir 搜索包含文件的目录
-j [N] 并行执行 N 个任务
-k 出错后继续
-l [负载] 负载限制
-L 检查符号链接时间戳
-n 只打印不执行
-o file 假装文件未过时
-O[类型] 输出同步:target, line, recurse, none
-p 打印数据库
-q 问题模式
-r 不使用内置隐式规则
-R 不使用内置变量
-s 静默模式
-S 取消 -k
--shuffle[=模式] 随机化构建顺序(测试依赖完整性)
-t touch 目标
--trace 跟踪信息
-v 版本信息
-w 打印工作目录
-W file 假装文件已修改

9.7 退出状态

  • 0 --- 成功
  • 1 --- -q 模式下目标不是最新的
  • 2 --- 发生错误

10. 隐式规则

10.1 使用隐式规则

隐式规则(隐含规则)让 make 自动推断如何从一种文件生成另一种文件。例如,make 知道如何从 .c 文件生成 .o 文件:

makefile 复制代码
foo.o: foo.c   # 不需要写配方,make 会自动使用 cc -c

10.2 内置规则目录

GNU make 内置了大量隐式规则,包括:

  • C 编译:%.o : %.c$(CC) -c $(CPPFLAGS) $(CFLAGS)
  • C++ 编译:%.o : %.cc$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
  • 汇编:%.o : %.s$(AS) $(ASFLAGS)
  • 链接:% : %.o$(CC) $(LDFLAGS) ...
  • 更多:Fortran、Pascal、Yacc、Lex、RCS、SCCS 等

10.3 隐式规则使用的变量

变量 默认值 说明
CC cc C 编译器
CXX g++ C++ 编译器
CFLAGS (空) C 编译器标志
CXXFLAGS (空) C++ 编译器标志
CPPFLAGS (空) 预处理器标志
LDFLAGS (空) 链接器标志
LDLIBS (空) 链接库
AR ar 归档工具
ARFLAGS rv 归档标志
AS as 汇编器
ASFLAGS (空) 汇编器标志
RM rm -f 删除命令

10.4 隐式规则链

make 可以链接多个隐式规则。例如,从 .y(Yacc)文件生成 .o 文件:

.y.c.o

10.5 模式规则

模式规则是定义隐式规则的主要方式:

makefile 复制代码
%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
  • % 通配符匹配任意非空子串
  • 匹配的部分称为"茎"(stem),可通过 $* 访问
模式规则示例
makefile 复制代码
# 从 .c 编译到 .o
%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

# 从 .y 编译到 .c
%.c : %.y
    $(YACC) $(YFLAGS) $<
    mv y.tab.c $@
匹配任意模式规则
makefile 复制代码
% : %.c
    $(CC) $(CFLAGS) $< -o $@
取消隐式规则

定义一个没有配方的模式规则来取消内置规则:

makefile 复制代码
%.o : %.c

10.6 最后手段规则

当没有其他规则可用时使用:

makefile 复制代码
.DEFAULT:
    @echo "Don't know how to make $@"

10.7 后缀规则(旧式)

旧式隐式规则定义方式,保留用于兼容性:

makefile 复制代码
.c.o:
    $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

等价于模式规则 %.o : %.c


附录:快速参考

指令汇总

指令 说明
define variable / endef 定义多行变量
undefine variable 取消变量定义
ifdef / ifndef / ifeq / ifneq / else / endif 条件判断
include / -include / sinclude 包含其他 makefile
override variable-assignment 覆盖变量
export / unexport 控制变量导出
private 禁止变量继承
vpath pattern path 设置搜索路径

特殊目标

目标 说明
.PHONY 声明伪目标
.SUFFIXES 后缀列表
.DEFAULT 默认规则
.PRECIOUS 保留中间文件
.INTERMEDIATE 中间文件
.SECONDARY 二级文件
.SECONDEXPANSION 启用二次展开
.DELETE_ON_ERROR 出错时删除目标
.IGNORE 忽略错误
.LOW_RESOLUTION_TIME 低精度时间
.SILENT 静默模式
.EXPORT_ALL_VARIABLES 导出所有变量
.NOTPARALLEL 禁止并行
.ONESHELL 单 shell 执行
.POSIX POSIX 兼容模式
.WAIT 等待前置条件完成
.NOEXPORT 禁止导出

特殊变量

变量 说明
MAKEFILES 每次调用 make 时读取的 makefile
VPATH 目录搜索路径
SHELL shell 程序(默认 /bin/sh)
MAKE make 命令名
MAKE_VERSION make 版本号
MAKE_HOST 构建主机
MAKELEVEL 递归层级
MAKEFLAGS make 标志
GNUMAKEFLAGS GNU make 特定标志
MAKECMDGOALS 命令行目标
CURDIR 当前工作目录
SUFFIXES 默认后缀列表
.LIBPATTERNS 库搜索模式
.RECIPEPREFIX 配方前缀字符(默认 Tab)
.VARIABLES 所有变量列表
.FEATURES 可用功能列表
.INCLUDE_DIRS 包含搜索目录
.EXTRA_PREREQS 额外前置条件
.SHELLSTATUS 上次 shell 函数退出状态

函数汇总

函数 说明
$(subst from,to,text) 替换子串
$(patsubst pattern,replacement,text) 模式替换
$(strip string) 去除空白
$(findstring find,in) 查找子串
$(filter pattern...,text) 筛选匹配
$(filter-out pattern...,text) 筛选不匹配
$(sort list) 排序去重
$(word n,text) 取第 n 个单词
$(words text) 单词计数
$(wordlist s,e,text) 取单词范围
$(firstword names...) 第一个单词
$(lastword names...) 最后一个单词
$(dir names...) 目录部分
$(notdir names...) 文件名部分
$(suffix names...) 后缀
$(basename names...) 基本名
$(addsuffix suffix,names...) 添加后缀
$(addprefix prefix,names...) 添加前缀
$(join list1,list2) 连接列表
$(wildcard pattern) 通配符匹配
$(realpath names...) 规范路径
$(abspath names...) 绝对路径
$(error text...) 致命错误
$(warning text...) 警告
$(info text...) 信息
$(shell command) 执行 shell 命令
$(origin variable) 变量来源
$(flavor variable) 变量风格
$(let var...,words,text) 绑定变量
$(foreach var,list,text) 循环
$(if condition,then,else) 条件
$(or condition...) 逻辑或
$(and condition...) 逻辑与
$(intcmp lhs,rhs,lt,eq,gt) 数值比较
$(call var,params...) 调用用户函数
$(eval text) 求值
$(file op filename,text) 文件操作
$(value var) 原始值
相关推荐
广州灵眸科技有限公司1 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) Easy-Eai编译环境准备与更新
服务器·前端·人工智能·python·深度学习
江澎涌2 小时前
拆解与 AI 的一次对话
人工智能·算法·程序员
Esaka_Forever2 小时前
uv init 完整用法(Python 最快包管理器)
服务器·python·uv
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.06.02 题目:3635. 最早完成陆地和水上游乐设施的时间 II
笔记·算法·leetcode
Lsk_Smion2 小时前
力扣实训 _ [102].层序遍历--前序--后续_递归与非递归的实现
数据结构·算法·leetcode
溜达的大象2 小时前
服务器挂了等用户报障?我用Prometheus搭了一套监控告警,服务器出状况第一时间通知我
服务器·php·prometheus
小欣加油4 小时前
leetcode3751 范围内总波动值I
java·数据结构·c++·算法·leetcode
闪电悠米4 小时前
黑马点评-Redisson-01_why_redisson
java·服务器·网络·数据库·缓存·wpf
Halo_tjn5 小时前
反射与设计模式1
java·开发语言·算法