Makefile学习记录(一)

在项目开放中使用makefile编译项目,在学习使用过程中出现了一些问题,这里做一些记录备份,已提供后面回顾


1makefile的函数理解

函数定义方法

define func_name

some_operation

endef

 

实际上makefile本质上是一种多行变量:

如:

define func_name

var := $1

endef

 

value :=$(call func_name,param1,……)

 

value的最后结果是

value = var:=param1

 

为了验证一下,编写简单的makefile测试一下:

然后make一下,结果如下:


可以看出value的值实际上就是test的展开式,那么我们在test函数中添加多行操作看看会有什么变化,修改后如下:


添加var1 = 123,然后执行make,会有报错:

这是为什么呢,其实只要将test展开就知道了:

value = var := 123

     var1:= 123

 

target执行时就是这样的:

target:

         echo var:=123

   var1:= 123

 

因为在var1之前有tab空格所以var1被当做了make的指令执行,单实际上make没有这个执行,所以报错为var1 命令没有找到,由此可以看出定义函数是这一点要尤为重视,否者函数的引用很容易出现问题。

 

 

2. eval函数的理解

make GNU对该函数做了细致的描述:

简单翻译一下:

函数“eval”是一个比较特殊的函数。使用它可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。

函数“eval”的返回值时空

尤为重要的是 eval”函数执行时会对它的参数进行两次展开。:“eval”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。明确这一过程对于使用“eval”函数非常重要。理解了函数“eval”二次展开的过程后。实际使用时,如果在函数的展开结果中存在引用(格式为:$(x)),那么在函数的参数中应该使用“$$”来代替“$”。因为这一点,所以通常它的参数中会使用函数“value”来取一个变量的文本值

简单点来说就是$(eval  text)会将text展开当做makefile的一部分,被make执行,所以text会被展开二次,第一次是eval展开,第二次则是作为被make执行进行的展开。还有一点需要特别注意eval的返回值是空,所以不能出现诸如:value := $(eval text)这类使用,value只能为空

 

说了这么多还是用实例测试一下:

定义一个函数,目的是获取本地目录,如上,执行make

可以看出value的值,但是$(local_dir)这个变量的值时空,为什么会这样,实际上我们将函数展开就理解了:

value := local_dir := /home/jimmy/workspace/my_study/test

target:

         @echolocal_dir:

看出来没有,makefile中没有定义local_dir这个变量。但是这个和eval有什么关系,不要紧我们来修改一下:


 

然后make一下:


可以看出value的值时空,因为eval的返回值是空,而local_dir这个变量这时候被定义了,而且还被赋值了。到这读者是否看出来了eval的作用。

         实际上就是eval展开了eval_test这个函数,并将其作为makefile的一部分送给make执行了一下,这样local_dir就被定义了;这个和call函数有明显的区别,call仅仅是将函数按照多行变量展开了,并不会送给make去执行;

 

猜测:

不过在上述例子中有个奇怪的点就是$(shell pwd)按照手册需要添加$$但是没有添加其结果好像也没有影响,那么修改一下如何:


再次make


 

还是没有影响,这是为什么,我猜猜是和$(shell pwd)的展开时间有关,在$(call eval_test)时就已经执行,这时候函数展开为local_dir := $/home/jimmy/workspace/mystudy/test,然后evallocal_dir :=$/home/jimmy/workspace/mystudy/test送给make作为makefie一部分执行。那为什么在输出是$这个符号不见了,测试一下。


执行make


可以看出Value2的输出为空,那么是否单个$会被忽略呢?

 

那么我们再添加一个试试呢:


输出错误:


这个真是很奇怪原因是什么呢!我们可以来展开一下。

第一次是call函数展开:

local_dir := $$$/home/jimmy/workspace/mystudy/test

然后eval展开:

local_dir :=$$ /home/jimmy/workspace/mystudy/test

 

然后执行

local_dir :=$$/home/jimmy/WorkSpace/my_study/test

echo时:把$$/home/jimmy/WorkSpace/my_study/test作为一个shell变量,然后会发现shell中不存在该变量,然后报错??

以上还有很多疑问,后续学习补充

 

 

3makefile的一些注意点

Makefile中所有以$打头的单词都会被解释成Makefile中的变量。如果你需要调用shell中的变量(或者正则表达式中锚定句位$),都需要加两个$符号($$)。实例如下:

PATH="/home/jimmy"

all:

   echo ${PATH}

   echo $$PATH

例子中的第一个${PATH}引用的是Makefile中的变量,而不是shell中的PATH环境变量,后者引用的事Shell中的PATH环境变量。

 

在目标文件冒号后在起一行,并且有tab空格则作为shell执行

target:

         value= $(value2)   shell执行

 

targetvalue = $(value2)   作为makefile 的代码

 

target

value = $(value2)   作为makefile 的代码

 

Makefile中的shell,每一行是一个进程,不同行之间变量值不能传递。所以,Makefile中的shell不管多长也要写在一行。



猜你喜欢

转载自blog.csdn.net/kuang_tian_you/article/details/80783996