Makefile 简单引入

本贴最后更新于 2056 天前,其中的信息可能已经时移俗易

Targets and dependencies

make 程序试图通过一个 target 带动起所有 target 的依赖保持更新. 这些依赖或许还会有更多的依赖关系. 所以当在处理一个"Makefile"的时候一个潜在的复杂的依赖关系图就会形成. 一个简单的"Makefile"长这样:

all: foo foo: foo.o bar.o baz.o .c.o: $(CC) $(CFLAGS) -c $< -o $@ .l.c: $(LEX) $< && mv lex.yy.c $@

我们也可以画出来这个依赖关系图:

foo
all
foo.o
bar.o
baz.o
foo.c
bar.c
baz.l
baz.c

"all"这个 target, 是一个文件名. 必须要写一些规则来通过规则来生成这个文件, 并且保持更新.
当在依赖图中找到叶子结点时, "Makefile" 必须包含一系列的 shell 命令使得依赖者和被依赖者保持更新. 使得 make 用户很恼火的是, 更新意思是说依赖者有着更新的时间戳, 相较于 target. 此外, 每个这样的 shell 命令都在它们自己的子 shell 中运行, 除非说是 Makefile 对 make 提出了明确的指示, 否则每一个命令必须以 0 退出码来说明执行成功了.
Target 规则也可以是无条件的执行, 这种情况是指定的 target 是没有依赖关系的. 我们熟悉的不能再熟悉的:

clean: -rm *.o core

Makefile syntax

"Makefile"有着比较特殊的语法规则,这也是困扰住初学者的原因之一. 那里有着许多 make 的实现, 一些还提供不可移植的扩展. 下面对语法进行简单的阐述, 为了便于可移植性, 可能会比你自己习惯的更加严格.
注释以"#"开头, 它们能出现在任何地方, 除了在命令序列中--因为会当成命令去执行了. 下面的这个"Makefile"展示了三个独立的 target 在自己名下的依赖关系:

target1: dep1 dep2 ... depN <tab> cmd1 <tab> cmd2 <tab> ... <tab> cmdN target2: dep4 dep5 <tab> cmd1 <tab> cmd2 dep4 dep5: <tab> cmd1

Target 规则是在行的开头开始,紧接着就是":", 然后后面跟着的就是以空格分割的依赖. 接下来几行几行的就是执行的 shell 命令. (默认是 Bash). 需要注意的是, 每一行都必须是以 tab 进行缩紧. 这个是新人最容易犯的错误.
这些 shell 命令的前面是可以加"@"前缀, 表示的就是使命令在被执行前不被回显, 在 make 执行时候, 输出的信息中, 不要显示此行命令. 也可以加上"-", 就是, 忽略当前此行命令执行时候所遇到的错误. 而如果不忽略, make 在执行命令的时候, 如果遇到 error, 会退出执行的, 加上减号的目的, 是即便此行命令执行中出错, 比如删除一个不存在的文件等, 那么也不要管, 继续执行 make.

Macros

一系列非常有用的宏贯穿着整个 Makefile. 宏是用"$"打头, 就像是 shell 变量:

$(CC) $(CFLAGS) -c $< -o $@

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...