以下转载自:https://blog.csdn.net/freestep96/article/details/126352344
Makefile命令参数、调用其他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=
Makefile遍历层级目录
以下转载自:Makefile遍历层级目录_makefile遍历文件夹文件_robin.L的博客-CSDN博客
针对多文件夹makefile编写,可以写一个通用makefile,遍历出每个文件夹,然后执行每个文件夹makefile,这样好处就是我们只需添加我们新增加的目录里面makefile,而不必理会之前的文件夹结构,非常方便。
1.首先遍历当前目录SRC_PATH下文件夹
SRC_FOLDER := $(shell find $(SRC_PATH) -maxdepth 1 -type d)
BASE_SRC_FOLDER := $(basename $(patsubst $(SRC_PATH)/%, %, $(SRC_FOLDER)))
2.其次过滤掉一下目录结构
BASE_SRC_FOLDER := $(filter-out $(SRC_PATH), $(BASE_SRC_FOLDER))
3.最后就可以遍历各个目录,执行各个子目录的makefile
default:
@for dir in ${BASE_SRC_FOLDER}; do make -C $(CUR_PATH)/$$dir ||exit; done
clean:
@for dir in ${BASE_SRC_FOLDER}; do make -C $(CUR_PATH)/$$dir clean ||exit; done
makefile结构如下:
CUR_PATH := $(shell pwd)
PRJ_PATH := $(CUR_PATH)/..
SRC_FOLDER := $(shell find $(CUR_PATH) -maxdepth 1 -type d)
BASE_SRC_FOLDER := $(basename $(patsubst $(CUR_PATH)/%, %, $(SRC_FOLDER)))
BASE_SRC_FOLDER := $(filter-out $(CUR_PATH), $(BASE_SRC_FOLDER))
BASE_SRC_FOLDER := $(filter-out lib, $(BASE_SRC_FOLDER))
BASE_SRC_FOLDER := $(filter-out obj, $(BASE_SRC_FOLDER))
.PHONY:default clean
default:
@for dir in ${BASE_SRC_FOLDER}; do make -C $(CUR_PATH)/$$dir ||exit; done
@echo build project done!
clean:
@for dir in ${BASE_SRC_FOLDER}; do make -C $(CUR_PATH)/$$dir clean ||exit; done
@echo clean project done!
获取相应目录,并排出相应目录
DIR = $(shell find $(HOME)/ -type d | grep -v "a" | grep -v "b"
获取相应目录的源代码
SRCS = $(sort s(foreach file_dir, $(DIR), $(wildcard $(file_dir)/*.c)))
生成源代码对应的目录
INCLUDES = $(sort $(foreach file_dir, $(DIR), $(addprefix -I, $(file_dir))))
获取相应目录,并排出制定目录
SRN = $(sort $(foreach file_dir, $(SRCS), $(notdir $(file_dir))))
联合使用
SRCS = $(sort $(foreach of, $(foreach file, $(LINKS), $(notdir $(file))), $(addprefix $(DIR)/, $(of))))