• Makefile基本语法
Makefile基本语法:
目标:依赖
Tab 命令  #注意:一定是要“Tab键”,空格不行

  • 通配符

什么是通配符?学过其他编程语言的可能只要什么叫通配符,通配符是一种特殊语句,主要有星号(*)和问号(?),用来模糊搜索文件。当查找文件夹时,可以使用它来代替一个或多个真正字符。

Makefile常见通配符:

%.o或%.c : 该通配符表示任意的.o文件或者.c文件
$@ : 表示目标
$< : 表示第一个依赖文件
$^ : 表示所有依赖文件

目标:一般指的是待编译的目标,也可以是一个动作

依赖:执行当前目标所要依赖的前提条件,包括其他目标、某个具体文件或库(一个目标可以有多个依赖)

命令:达到该目标需要执行的具体命令,可以为空;也可有多条,多条时,每条命令单独一行

  • make常用选项

  首先,了解一下make命令的基本用法

make [-f file] [options] [target]
执行make命令,默认在当前目录中寻找GUNmakefile、makefile文件,作为make命令的输入文件
 - -f 可指定上述文件名之外的文件作为输入文件
 - -v 显示版本号
 - -n 只输出命令,但并不执行,一般用于调试或测试
 - -s 只执行命令,但不显示具体命令,此处可在命令中用@符号抑制命令输出
 - -w 显示执行前、后的路径
 - -C [dir] 指定makefile的目录
 
 没有指定目标时,默认使用第一目标
 如果指定,则执行对应的命令

常见的make命令:
make 按默认配置編译
make -j8           8个进程同时编译,缩短总的时间
make world         编译所有能够编译的(postgresql 经常同时編译文档及附加模块(contrib)
make check         回归测试,用于安装完成后测试功能完整性,不能以 root 身份运行

make install       安装程序
make install-docs  安装文档(info、man手册)
make install-world 安装所有可安装的

make uninstall     删除安装的文件(生成的目录无法删除)

make clean         清除 make 生成的文件,但保留 configure 生成的文件
make distclean     将源码恢复为原始状态,即同时删除 make 与 configure 阶段生成的文件

make -C 指定源文件目录,仅安装程序的特定部分;
        如只安装客户端应用和接口:
		make -C src/bin install; 
		make -C src/include install; 
		make -C src/interfaces install; 
		make -C doc install

  • Makefile变量的引用与赋值


1.自定义变量
  Makefile文件中的几种赋值与引用方式:=、:= 、?=、+=,赋值操作一般是针对变量的,Makefile中的变量可以任意命名,原则上尽量见名知意。
(1)= 递归式变量赋值(可以理解为是C语言里的传址),左侧为变量名,右侧为变量的值,优点是变量可以重复多次赋值

xxx@XXX:~/test$ cat Makefile
var1=1
var2=$(var1)
var2=2
print:
	echo $(var2)

xxx@XXX:~$ make
echo 2
2

(2):= 展开式变量赋值(可以理解为是C语言里的传值),定义变量时,变量右侧的值立即替换到变量值中,前面的变量不能使用后面的变量,即变量一旦赋值,即使后面再次赋值,也不会覆盖前面定义的变量值

xxx@XXX:~/test$ cat Makefile
var1=012
var2:=$(var1)
var1=345
print:
	echo $(var2)

xxx@XXX:~/test$ make
echo 012
012

(3)?= 条件赋值,用于判断左边的变量是否被赋值过,如果是,不会执行此次赋值操作;如果不是,则给该变量赋值:

xxx@XXX:~/test$ cat Makefile 
var1=012
var2=$(var1)
var2 ?=345
print:
	echo $(var2)
	
xxx@XXX:~/test$ make
echo 012
012

(4)+= 一般用于新增目标文件编译操作,例如:

#新增目标前
objs=main.o add.o
main=$(objs)
#此时需要新增一个sub.o文件
objs=main.o add.o 
objs+=sub.o 
main=$(objs)

2.系统变量(自动变量)

自动变量名解释说明
$@表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,也称为静态的库文件),那么它代表这个文档的文件名;在多目标模式规则中,它代表的是触发规则被执行的文件名
$%当目标文件是一个静态库文件时,代表静态库的一个成员名;如果目标文件不是静态库文件,其值为空
$<规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,则它代表由隐含规则加入的第一个依赖文件。
$?所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。
$^代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有的库成员(.o 文件)名。一个文件可重复的出现在目标的依赖中变量,只记录它的第一次引用的情况。就是说变量“^”会去掉重复的依赖文件。
$+类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。
$*在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时,“茎”也包含目录部分)。
常见的自动变量类型

2.系统常量(内置变量)

CURDIR := /home/zht # 记录当前路径
SHELL = /bin/sh
MAKEFILE_LIST :=  Makefile
.DEFAULT_GOAL := all
MAKEFLAGS = p
HOSTARCH := x86_64
CC = cc 		# C语言编译器的名称
CPP = $(CC) -E  # C语言预处理器的名称 $(CC) -E
CXX = g++       # C++语言的编译器名称
RM = rm -f		# 删除文件程序的名称
CFLAGS			# C语言编译器的编译选项,无默认值
CPPFLAGS  		# C语言预处理器的编译选项,无默认值
CXXFLAGS		# C++语言编译器的编译选项,无默认值
  • Makefile模式规则


1.模式规则
  模式规则类似于普通规则,只是在模式规则中,目标名中需要包含有模式字符“%”(一个),包含有模式字符“%”的目标被用来匹配一个文件名,“%”可以匹配任何非空字符串。规则的依赖文件中同样可以使用“%”,依赖文件中模式字符“%”的取值情况由目标中的“%”来决定。
  例如:对于模式规则“%.o : %.c”,它表示的含义是:所有的.o文件依赖于对应的.c文件。我们可以使用模式规则来定义隐含规则。要注意的是:模式字符“%”的匹配和替换发生在规则中所有变量和函数引用展开之后,变量和函数的展开一般发生在make读取Makefile时,而模式规则中的“%”的匹配和替换则发生在make执行时。

2.Makefile伪目标
  Makefile中存在一种伪目标,我们生成了许多文件编译文件,我们也应该提供一个清除它们的“目标”以备完整地重编译而用。 (以“make clean”来使用该目标) ,调用相应的规则,来清除许多编译的文件(如:*.o文件)因为,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。
  当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
.PHONY : clean
只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”这样。于是整个过程可以这样写:

.PHONY: clean
clean:
rm *.o temp


  伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。示例,如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make,并且,所有的目标文件都写在一个Makefile中,那么你可以使用“伪目标”这个特性:

 all : prog1 prog2 prog3
    .PHONY : all

    prog1 : prog1.o utils.o
            cc -o prog1 prog1.o utils.o

    prog2 : prog2.o
            cc -o prog2 prog2.o

    prog3 : prog3.o sort.o utils.o
            cc -o prog3 prog3.o sort.o utils.o 

一个电子工程师的自我修养