最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】一个makefile中export出来的变量在另外一个makefile中无法访问

工作和技术 crifan 1791浏览 0评论

【问题背景】

一个大的系统,通过一个总的make控制整个项目编译过程。

具体make的流程是,在/make下面直接make,会先去make uboot,再去make kernel,然后去make其他的,比如drivers等等。

遇到的问题是,由于是使用交叉编译器,对应的交叉编译器的路径,是在uboot中定义的,所以uboot是可以正常交叉编译的。

但是编译完uboot,转去编译kernel的时候,却出错,说是找不到交叉编译器。

即问题的现象是,找不到交叉编译器:

/bin/sh: bfin-uclinux-gcc: command not found
【解决过程】

现象看起来很简单,就是具体的交叉编译器的路径,没有正确配置。

但是具体为何没有添加对应交叉编译器的路径,去找原因,最后却发现根本原因是,对应交叉编译器的路径,是在uboot中配置的,然后通过export CROSS_COMPILE导出该变量,供后续编译其他部分代码所使用。

刚开始,自己的理解有误,以为整个逻辑是,在make之后,由于是先make uboot,再make kernel,所以交叉编译器的变量的值,是通过在uboot中配置好,然后export出来给后续的kernel,drivers等部分编译的时候使用。

但是后来才发现,自己理解错误。

因为uboot和kernel,两者的MAKELEVEL(可以通过echo $(MAKELEVEL)查看当前makefile的level)是同一级的,MAKELEVEL都是2,对应的最开始的make的MAKELEVEL是0.

所以,经过测试,发现通过export出来的变量,在MAKELEVEL=0的make中,是可以传递给子makefile(sub-make)中的uboot的,而通过同一级的makefile,即两者的MAKELEVEL相同,是没法用export传递变量的。

即uboot和kernel,uboot中export出来的变量,是不能传递给kernel的。

而如果uboot中设置的CROSS_COMPILE的变量无法传递给kernel,那么此项目,之前的人,是如何正常编译的呢?最后通过问别人才得知,原来,就是最简单的,把交叉编译器的变量,加到.bash_profile中的$PATH中去,如此而已。这样,就可以在编译kernel的时候,找到对应的交叉编译器了。而不是通过在uboot中export出来CROSS_COMPILE来获得交叉编译器路径的。

此问题,前后花了很长时间去debug,中间,不知道什么原因,导致我测试在总的make,即MAKELEVEL=0的makefile中,传递变量到MAKELEVEL=2的uboot中,结果却发现正常传递参数,搞得很是郁闷,但是后来再次测试,却又正常了,即可以通过上层的makefile,export出来变量给sub makefile中了。真是无语了。

另外,关于在makefile中export出来的变量,可以传递给sub make中,网上很多资料介绍这方面内容的,比如:

http://www.gnu.org/s/hello/manual/make/Variables_002fRecursion.html#Variables_002fRecursion

但是对于同级makefile通过export传递变量,没有看到人讨论过,此处经过自己的测试,发现的确是无法传递的。

 

【makefile中的export和shell中的export】

对于测试,在上层makefile中,用export导出变量,传递给子makefile时,看看子makefile中是否可以访问该变量。

其中,在最上层的makefile中,这样测试的:

 carifan_TopMake=E516537_in_top_make
#export carifan_TopMake
focus_bfin
:
        echo current make MAKELEVEL=$(MAKELEVEL)
        export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

   

然后make focus_bfin后,发现在focus_bfin下面,export出来的carifan_TopMake,在子makefile中打印出来的是空的,即实际上该变量没有被export出来。

而后来无意间,用下面这样的方式测试:

 carifan_TopMake=E516537_in_top_make
export carifan_TopMake
focus_bfin
:
        echo current make MAKELEVEL=$(MAKELEVEL)

        #export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

   
结果就是,可以正常export出来变量,然后子makefile中,可以得到该变量的值。

所以,对此现象,经过后来的折腾,发现不是所谓什么makefile中变量的作用域之类的问题,

而是在makefile中的export和shell中的export作用不同:

在focus_bfin上面那行的“export carifan_TopMake”,

是makefile中的export,其作用是导出一个变量,使得子makefile,即当前makefile所派生的的makefile,即通过如下某种形式:

make XXX

make -f XXX.mak

include XXX.mak

而相关的子makefile。

focus_bfin:
        echo current make MAKELEVEL=$(MAKELEVEL)

        #export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

  

中的目标是“focus_bfin”,然后该目标对应的那些行的代码,都是make要去执行的动作,对于每一行,都会新启动一个shell,去执行对应的命令,因此,上面的focus_bfin中的export:

 #export carifan_TopMake

和下面的那行的make:

      make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

 是没有关系的,是分别属于两个shell的。

经过折腾后,对应地,这样是可以成功导出变量的:

 #export carifan_TopMake

#carifan_TopMake=E516537_in_top_make_global

focus_bfin:

        echo current make MAKELEVEL=$(MAKELEVEL)

        echo “*****************test Value in Top Makefile=$(carifan_TopMake)”;

        carifan_TopMake=E516537_in_top_make_local;export carifan_TopMake; make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

 

【疑问】

不过,虽然理解了上面的makefile中的export和shell中的export是不同的,但是对于下面的这样的例子:

 carifan_TopMake=E516537_in_top_make_global

focus_bfin:

        echo current make MAKELEVEL=$(MAKELEVEL)

        echo “*****************test Value in Top Makefile=$(carifan_TopMake)”;

        export carifan_TopMake=E516537_in_top_make_local; echo “in same shell line,carifan_TopMake=$(carifan_TopMake)”; make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

 其echo输出的内容,却是   

 echo “in same shell line,carifan_TopMake=E516537_in_top_make_global

   而不是我所期望的:

 echo “in same shell line,carifan_TopMake=E516537_in_top_make_local

   而看到别人有关于makefile中的$XXX的解释,说makefile会去自动将$XXX替换为相应的内容,所以对于上面的内容:

 echo “in same shell line,carifan_TopMake=$(carifan_TopMake)”;

其自动会替换成:

 echo “in same shell line,carifan_TopMake=E516537_in_top_make_global“;

   所以就相当于在shell中执行:

 export carifan_TopMake=E516537_in_top_make_local; echo “in same shell line,carifan_TopMake=E516537_in_top_make_global“;

但是,我去尝试:

 echo “in same shell line,carifan_TopMake=$carifan_TopMake”;

或者 

 echo “in same shell line,carifan_TopMake=$$carifan_TopMake”;

 输出的结果,都无法实现想要的:

 echo “in same shell line,carifan_TopMake=E516537_in_top_make_local“;

 而相对的,在shell中执行类似的动作,是可以echo出来对应的变量的:

 export carifan_TopMake=E516537_in_top_make_local ; echo “$carifan_TopMake”

–>
E516537_in_top_make_local

   而此处却始终无法实现像shell中一样的结果,显示我的E516537_in_top_make_local的值。

截止目前,还是没搞懂这点。。。

 

【总结】

1.在(parent,上层的)makefile中export出来变量,子makefile(sub make)中,是可以访问的。

2. 而同一级别的makefile(可通过makefile中内置变量MAKELEVEL查看得知当前makefile的levlel),是无法通过export来传递变量的,即一个makefile中export出来一个变量,同一级的另外一个makefile中,是无法访问/得到的。

3.makefile中的export是导出变量到子makfile,而目标对应执行的动作中的export,是属于shell中的export,其作用是导出变量到当前shell。此两个export的作用是不同的。

转载请注明:在路上 » 【已解决】一个makefile中export出来的变量在另外一个makefile中无法访问

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.109 seconds, using 20.54MB memory