A quick introduction to GNU make — Di 23 Juli 2024

你好,世界!

最近,我给一个实习生布置一些编程的任务。实习生学习过 c 语言,对语法和算法都有一定的掌握。不过,他们在学校使用的是 Windows,而且从来没用过 GNU make。这是一个多么可悲的事情啊!学习 c 语言 GCC 和 GNU make 是多好的一对搭档,也是大多数有一定规模的项目会使用的基本工具。于是,我就给实习生做了一个 make 的简单介绍,便于他快速使用。

由于平常主要使用 GNU autotools,它隐藏了许多细节,我发现自己对 make 也还要再看一下才能确认。所以这个介绍对我也是温故知新。

make 语法

make 的语法非常简单,一看就会。make 会查找当前目录的一个 Makefile 文件,其基本结构如下:

target1 [target2 ...]: [pre-req-1 pre-req-2 ...]
    [command1
     command2
     ......]

说明:

  1. 冒号(:)前面的 target1([]里面是可以省略项目)是要生成的目标或结果。对 c 项目来说,目标可以是 .o 文件或 .exe 文件。
  2. 冒号(:)后面的 pre-req-1 等等是生成目标所需要的前提,可以没有。对 c 项目来说,前提可以是 .c 文件,也可以是 .o 文件。
  3. 下面的 command1 等等是 make 要执行的命令,可以是编译命令,也可以是其他命令。注意命令行以 tab 按键开头。

执行 make 的话,只需在有 Makefile 的目录下从命令行执行:

make [target]

注释

Makefile 的注释以 “#” 字符开始,直至行尾。

写明目标、前提和命令

最直白的 Makefile 会明确写出所有的依赖,比如

# default target is all
all: hello.exe

hello.exe: hello.c
     gcc -g hello.c -o hello.exe

clean:
     rm hello.exe

说明:

make

那么,执行的结果和输入命令:

make all

是一样的。

make clean

直接执行命令

rm hello.exe

通配符

当我们的文件比较多的时候,我们需要一些方法来减少输入。这里就可以用到 make 的通配符。

*

'*' 可以用来代替文件名的任意字符串,比如我们可以在 Makefile 里写:

clean:
        rm *.exe

那么执行命令

make clean

就会删除当前目录的所有以 exe 结尾的文件。

内置宏定义

make 支持很多内置的宏定义。我们常用的有这么两个:$^ 和 $@

  1. $^:匹配目标的所有前提。
  2. $@:匹配目标。

我们可以在 Makefile 里写:

hello.exe: hello.c
           gcc -g $^ -o $@

此时,$^ 就是 hello.c,$@ 就是 hello.exe。这在前提很多的时候非常方便。

%

'%' 有多种用法。我们现在只说它在 make 中的文件名模式替换功能。举个例子就能说明问题。

executables = hello-1.exe hello-2.exe hello-3.exe

all: $(executables)

$(executables): %.exe: %.c
    gcc -g $^ -o $@

执行命令

make

就会按照 executables 里的目标名字把每个对应的前提 c 文件编译连接成对应的目标 exe 文件。这就大大节省了输入各种文件名字的输入活动。

用 make 做测试

测试就是把实际运行结果和预期结果比较,判断二者是否一致的过程。如果我们把预期结果做成文件,那么我们就可以使用 make 来完成很多自动测试。举例如下:

test: hello.exe
      $^ < input.txt > output.txt
      diff expected.txt output.txt

运行命令

make test

就会根据输入 input.txt 输出实际结果 output.txt,并使用 diff 和预期结果 expected.txt 进行比较。如果比较结果不一致时,那么测试就会停止,diff 会输出显示不一致的内容,从而达到测试的目的。

至此,我们一起回顾了 make 的基本用法,实习生到此也完全了解了 make 的意义,后面多加练习就能熟练使用 make 这一强大的开发工具。如果进一步阅读 make 的手册和文档,那么将来在系统集成方面也能有更好的了解和贡献。

最后,需要指出 GNU make 是自由软件,你可以学习、修改、分享它。

如果你对 GNU make 还有问题,立伯乐或许可以帮你。

用 GNU make 会让你的开发如虎添翼、自由奔放!