GNU make 与 Makefile

前言

make 是一个工具程序,通过读取 Makefile 文件,实现自动化软件构建。虽然现代软件开发中,集成开发环境已经取代了 make,但在 Unix 环境中,make 仍然被广泛用来协助软件开发。make 不仅仅用来编译 C/C++ 程序,还可以用来实现任何输入文件和结果文件的转化。

Makefile 语法

Makefile 文件由一组规则构成,每个规则有如下形式:

targets : prerequisities
	recipe
	recipe
	recipe
  • targets:目标是文件名或操作名(也称为“伪目标”,phony target)。目标通常是一个,多个目标之间用空格分隔。
  • prerequisities:前置条件定义了构建目标文件的依赖。多个依赖文件(也可以是伪目标)用空格分隔。只要有一个前置文件不存在,或者有过更新(前置文件的最后修改时间比目标的时间戳新),目标就需要重新构建。如果前置条件不存在,会执行 make <prerequisities>。
  • recipe:每一行配方的起首是 tab 键,而不是空格。

如果存在 targets 同名的文件,make <targets> 不会执行。这时需要加上 .PHONY,伪目标会在每次编译时重新执行一遍。

.PHONY: clean
clean:
	rm *.o temp

如果 make 执行时没有指定目标,则默认执行 Makefile 中的第一个目标

注释

# 在 Makefile 中表示注释。

变量

可以在 Makefile 中使用变量。引用变量的方法是:$(变量名)

files = file1 file2
some_file: $(files)
	echo "Look at this variable: " $(files)

赋值运算符可以是:=,=:,?=,

  • = 只有在命令使用到该变量时,才执行赋值操作。在此之前,变量会原封不动地记录赋值语句右边的表达式。
  • =: 赋值语句立刻执行。如果该赋值语句右边表达式中含有变量,则该变量只有定义在赋值语句之前才会被应用。
  • ?= 赋值前会检查变量是否已经被赋值。如果已赋值则不执行此次赋值,否则执行

指令

include

include 指令会使 make 程序停在当前 makefile 文件读取位置,而先去读取指定文件,再继续读。
-include 同 include,但文件不存在时不会报错

include Makefile.common

控制流指令

使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支。下面的例子,判断 $(CC) 变量是否 gcc ,如果是的话,则使用GNU函数编译目标。

libs_for_gcc = -lgnu
normal_libs =

ifeq ($(CC),gcc)
    libs=$(libs_for_gcc)
else
    libs=$(normal_libs)
endif

foo: $(objects)
    $(CC) -o foo $(objects) $(libs)

ifeq 如果相等
ifneq 如果不相等

配方

显示命令

make 默认会把要执行的命令在执行前输出到屏幕上。但如果在命令行前用 @,则不会打印。比如下面的例子,只打印 >> writing assets,而不会打印 echo。

.PHONY: assets
assets:
	@echo ">> writing assets"

函数

字符操作函数

# firstword 打印第一个单词
$(firstword foo bar)

# word <N> 打印第 N 个单词
$(word 2, foo bar baz)

# wildcard <FILENAMES> 打印所有匹配的文件名,用空格隔开
$(wildcard *.md)

shell 函数

shell 函数执行 shell 后面跟着的参数,并把执行结果作为返回。

go = $(shell go version)

.PHONY: all
all:
	echo $(go)

参考文档

[1] 阮一峰:Make 命令教程
[2] GNU Make Manual
[3] 跟我一起写 Makefile

原文地址:https://www.cnblogs.com/huanggze/p/11914235.html