[工具使用:Makefile] Makefile学习笔记

本文详细介绍了Makefile的命令参数使用,包括-C、-f、-i等,以及如何通过`include`关键字引用其他Makefile。还探讨了Makefile的嵌套机制,如何通过`$(MAKE)`在子目录中调用make,并讲解了`export`和`unexport`用于变量传递。此外,展示了如何编写通用Makefile遍历多层次目录并执行子目录的Makefile。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下转载自: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))))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值