Make:目标(Target)构建的详细和依赖项的处理过程(个人总结)

相关文章

Make:默认构建目标(终极目标)


        这段时间在用makefile,所以自己探究了一下make的工作过程,并经过实验总结了一些规律。

         对于一个规则的处理如下,首先make会检查规则中的目标文件是否存在和依赖项的情况:

        如果没有目标文件的同时没有依赖文件项(即:后面为空),则规则的命令一定会直接执行。

        如果有目标文件的同时没有依赖文件项(即:后面为空),则规则的命令一定不会执行。

        如果没有目标文件的同时有依赖文件项,则规则的命令一定会在规则的所有依赖项文件被检查(和处理,如有)后执行。

        如果有目标文件的同时有依赖文件项,则会像下面一样先检查(和处理,如有)依赖项,是否执行规则的命令不确定。

        依赖项的检查(和处理,如有)是从左至右对各个依赖项进行检查,并可能会根据结果处理其他规则,只有一个依赖项的检查(和处理,如有)完毕才会开始下一个依赖项的检查(和处理,如有):

        1、如果某个依赖项文件不存在,则会在当前makefile中搜索是否存在以该依赖项文件为目标的规则对其进行处理,处理规则的方法与当前规则一致,同时当前规则的命令一定会在当前规则的所有依赖项文件检查(和处理,如有)后执行,如果没有找到以不存在的依赖项文件为目标的规则,则会报错。

        2、如果某个依赖项文件存在,也在当前makefile中搜索是否存在以该依赖项文件为目标的规则进行处理(这是make尝试更新依赖项文件),如果没有以该依赖项文件为目标的规则,则视为该依赖项检查完毕。

        3、如果所有依赖项文件在检查时都存在(即都如第2点一样,不管对这个依赖项是否处理了),则make会在所有依赖项文件检查完毕后,对目标文件和依赖项文件进行修改时间的对比,如果有一个依赖项比目标文件新,则会执行规则的命令。

例1:

main: main.o
	gcc -o main main.o

main.o: main.c
	gcc -c main.c -o main.o
	sleep 5
	gcc -o main main.o
	sleep 5

        对于以上的makefile,如果main文件不存在,则一定会在最后执行gcc -o main main.o构建。如果main.o不存在,main存在,也一定会在最后执行gcc -o main main.o构建,即使你在main.o中创建了main.o和main,并使main新于main.o,因为此时对于main和main.o的比较不会进行,在检查到main.o缺失时,gcc -o main main.o就注定要执行。

例2:

clean:
    echo clean

        对于以上的makefile,正常情况下,clean文件总是不存在的,所以每当make clean时都会执行echo clean命令,但如果人为使clean文件存在时,make clean时会告诉你clean已经是最新,因此需要伪目标的引入。

例3:

clean: clean1
    echo clean

clean1: 
    echo clean1

        对于以上的makefile,即使clean文件存在,make clean依然可以顺利执行两条echo,因为clean1文件不存在,所以目标为clean的规则的命令一定会在规则的所有依赖项文件被处理后执行。

        假如clean1和clean文件都存在,则会根据他们两个的修改时间决定是否执行echo clean,至于echo clean1是不会执行的,因为规则的目标clean1存在且规则无依赖项。

例4:

main: main.o
	gcc -o main main1.o

main.o: main.c
	gcc -c main.c -o main1.o

        以上的文件,在每次执行make时都会尝试构main.o,但因为命令的问题,只会构建main1.o。make在执行命令时,不会尝试理解命令,所以正确的命令是好的makefile的前提。

        顺带一提,如果人为插入一个main.o,则make时,main.o对应规则的命令是否执行,取决于main.o和main.c修改时间的对比,而main对应规则的命令是否执行,取决于main和main.o修改时间的对比。

你可能感兴趣的:(Make,linux,运维,服务器,make,makefile)