更多单片机/嵌入式内容及参考资料:大叔的嵌入式小站:

Makefile学习-3.make命令参数、调用其他makefile、嵌套

一、Make命令运行参数

参数        参数的作用 
-C        dir读入指定目录下的makefile 
-f        file读入当前目录下的file文件作为makefile 
-i        忽略所有命令执行错误 
-I        dir制定被包含的makefile所在目录 
-n        只打印要执行的命令,但是不执行这些命令 
-p        显示make变量数据库的隐含规则 
-s        在执行命令时不显示命令 
-w        如果执行make在执行过程中改变目录,打印当前目录名

二、调用/引用其他Makefile

    在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是:

include <filename> filename可以是当前操作系统Shell的文件模式(可以包含路径和通配符)

在include前面可以有一些空字符,但是绝不能是[Tab]键开始。include和可以用一个或多个空格隔开。举个例子,你有这样几个Makefile:a.mk、b.mk、c.mk,还有一个文件叫foo.make,以及一个变量$(bar),其包含了e.mk和f.mk,那么,下面的语句:

   include foo.make *.mk $(bar)

等价于:

   include foo.make a.mk b.mk c.mk e.mk f.mk

make命令开始时,会把找寻include所指出的其它Makefile,并把其内容安置在当前的位置。就好像C/C++的#include指令一样。如果文件都没有指定绝对路径或是相对路径的话,make会在当前目录下首先寻找,如果当前目录下没有找到,那么,make还会在下面的几个目录下找:

1.如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。

2.如果目录/include(一般是:/usr/local/bin或/usr/include)存在的话,make也会去找。

      如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在include前加一个减号“-”。如:

-include

其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令是sinclude,其作用和这一个是一样的。

config.mk文件内容如下:

OBJS=f1.o f2.o 
OBJS+=main.o 
CFLAGS=-c -Wall -I include

makefile文件内容如下:

include config.mk#调用config.mk文件的内容 
test:$(OBJS) 
    gcc $(OBJS) -o test 
f2.o:$< 
    gcc $(CFLAGS) f2.c -o $@ 
f1.o:f1.c 
    gcc $(CFLAGS) f1.c -o $@ 
main.o:main.c
     gcc $(CFLAGS) main.c -o mian.o 
.PHONY:clean 
    clean: rm *.o test

三、嵌套

当工程文件比较多时,如果只使用一个makefile会使得这个makefile显得比较繁琐复杂,那么我们可以通过使用makefile嵌套,内层使用子makefile,外层来调用这些子makefile。

如何来使用呢?举例说明如下:

subsystem: 
    cd subdir && $(MAKE)

这个例子可以这样来理解,在当前目录下有一个目录文件 subdir 和一个 makefile 文件,子目录 subdir 文件下还有一个 makefile 文件,这个文件是用来描述这个子目录文件的编译规则。使用时只需要在最外层的目录中执行 make 命令,当命令执行到上述的规则时,程序会进入到子目录中执行 make这就是嵌套执行 make,我们把最外层的 Makefile 称为是总控 makefile

上述的规则也可以换成另外一种写法:

subsystem:
    $(MAKE) -C subdir

在 make 的嵌套执行中,我们需要了解一个变量 “CURDIR”,此变量代表 make 的工作目录。

当使用 make 的选项 “-C” 的时候,命令就会进入指定的目录中,然后此变量就会被重新赋值。

总之,如果在 Makefile 中没有对此变量进行显式的赋值操作,那么它就表示 make 的工作目录。我们也可以在 Makefile 中为这个变量赋一个新的值,当然重新赋值后这个变量将不再代表 make 的工作目录。

export的使用:

使用 make 嵌套执行的时候,变量是否传递也是我们需要注意的。如果需要变量的传递,那么可以这样来使用:

export

如果不需要那么可以这样来写:

unexport

是变量的名字,不需要使用 “$” 这个字符。如果所有的变量都需要传递,那么只需要使用 “export” 就可以,不需要添加变量的名字。

Makefile 中还有两个变量不管是不是使用关键字 “export” 声明,它们总会传递到下层的 Makefile 中。这两个变量分别是 SHELL 和 MAKEFLAGS,特别是 MAKEFLAGS 变量,包含了 make 的参数信息。如果执行总控 Makefile 时,make 命令带有参数或者在上层的 Makefile 中定义了这个变量,那么 MAKEFLAGS 变量的值将会是 make 命令传递的参数,并且会传递到下层的 Makefile 中,这是一个系统级别的环境变量。

make 命令中有几个参数选项并不传递,它们是:"-C"、"-f"、"-o"、"-h" 和 “-W”。如果我们不想传递 MAKEFLAGS 变量的值,在 Makefile 中可以这样来写:

subsystem: 
    cd subdir && $(MAKE) MAKEFLAGS=

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐