我所认识的GNU make(5) -- make是如何处理Makefile的

来源:互联网 发布:u8软件 编辑:程序博客网 时间:2024/05/16 08:13

通常情况下Makefile的内容就是告诉make如何去编译和链接生成一个程序。并且默认情况下,make会以在Makefile中寻找到的目标作为这次执行make程序的最终目标,所以和最终目标不相干的规则make将忽略掉,不会去执行。或者你也可以在输入make命令的时候指明具体的目标。

你可以通过使用inclide指令将其他的makefile包含进来,如果你在include其他的makefile的时候没有指定其路径,那么make会到当前的目录里去找,如果没有找到指定的makefile,并且你在输入make命令的时候没有指定-I或者--include-dir选项,那么make还会去一下这些目录里面寻找:/usr/local/include,/usr/gun/include,/usr/local/include,/usr/include。

有时候Makefile可以从其他的文件生成,在这种情况下,为了能够得到最新的Makefile,每当make读取Makefile的时候就会将当前的Makefile也当作是一个目标(target)然后去尝试更新。如果make能够找到如何更新Makefile的方法,不管是显式规则还是隐含规则,那么make就会尝试着去更新Makefile,如果Makefile可以被更新,那么make就会先更新Makefile,然后将make当前的状态清零,再重新将Makefile读进来。

GNU make处理Makefile文件分为两大步:

1. 读进所有的Makefile,初始化所有的变量,隐含规则和显式规则,建立一张依赖表,该表包含所有的target和prerequisite,在这一步中,make会对Makefile中的变量进行展开,即使用变量的值(字符串)替代原来变量所在的位置;

2. make利用上一步建立的依赖表决定哪些target需要重建,然后将相应的recipe传给shell,让shell执行这些recipe。

第一步变量的展开中,有时候我们并不希望某些变量在规则中的target,prerequisite确定之前或者其他变量赋值之前就展开,那样就无法得到我们想要的值,这个时候就需要对这个Makefile进行二次展开,就是说make程序在第一次解析完Makefile后,再次对Makefile进行解析,对一些推迟展开的变量进行展开。如正常情况下,自动变量是只能在recipe中使用的,因为第一次展开之前make是无法知道这些自动变量的值的,当时等到第一次展开之后,所有的自动变量的值都已经确定,这时候就可以让make进行二次展开,这样就可以在recipe之外对自动变量进行使用了,这样就能够彻底地将自动变量从recipe的范围中释放出来。

如果要让make知道需要对某个Makefile进行二次展开的话,那么就需要在Makefile中定义.SECONDEXPANSION这个特殊的目标,一般情况下只需要写明这个目标,然后prerequisite和recipe都可以放空。那么怎么让某一个变量在二次展开的时候才生效呢?主要有两种方式:

1. 在变量定义的时候,将变量定义为循环展开变量而不是直接展开变量,即使用=或者?=对变量进行定义,而不是:=或::=(这是直接展开变量的定义方式),循环展开变量中如果不包含有其他的变量引用的话则跟直接展开变量是没有区别的,否则,make对Makefile进行第一次展开的时候,make只会将定义循环展开变量时的那一个字符串填充到变量位置,而不对循环展开变量中对其他变量的引用进行展开,等到第二次make对Makefile进行解析的时候才会看到那个原本在循环展开变量定义中被引用的变量,然后再对其进行展开;

2. 更简单的方法就是在变量引用的时候再多加一个$符号,就是说变量名前面有两个连续的$符号,例如$$var,所以如果在二次展开使能的情况下,如果你想要在prerequisite中使用一个$符号的时候,这时候你就需要写连续的四个$符号,即$$$$,因为在Makefile中都是以$符号作为变量引用的开始,在每一次解析中,需要连续两个$符号,make才会知道那是一个$字符。

其实这两种方法的本质是一样的,都是变量的嵌套引用。


写这个是本着大家一起学习探讨的目的,阅过的请留下您的宝贵意见,我会及时回复。

--The Magic That Brings Hardware To Life.

1 0
原创粉丝点击