之前我们学习了 makefile 中的变量及函数的相关语法知识,那么我们今天就来以实际需求为例来进行实际编写。实战需求:1、自动生成 target 文件夹存放可执行文件;2、自动生成 objs 文件夹存放编译生成的目标文件(*.o);3、支持调试版本的编译选项;4、考虑代码的扩展性。
那么在进行今天的 makefile 编写之前,我们还需要了解下几个知识点:a> $(wildcard _pattern),它的作用是获取当前工作目录中满足 _pattern 的文件或目录列表;b> $(addprefix _prefix,_names),它的作用是给名字列表 _names 中的每一个名字增加前缀 _prefix。
其中的关键技巧:1、自动获取当前目录下的源文件列表(函数调用):SRCS := $(wildcard *.c);2、根据源文件列表生成目标文件列表(变量的值替换):OBJS := $(SRCS:.c=.o);3、对每一个目标列表加上路径前缀(函数调用):OBJS := $(addprefix path/, $(OBJS))。
我们来看看规则中的模式替换(目录结构),如下
看看编译规则的依赖,如下
下来我们来看看具体的 makefile 是怎样编写的,还是以之前的那三个 .c 文件为源文件。
CC := gcc
MKDIR := mkdir
RM := rm -rf
DIR_OBJS := objs
DIR_TARGET := target
DIRS := $(DIR_OBJS) $(DIR_TARGET)
TARGET := $(DIR_TARGET)/hello-makefile.out
# main.c func.c const.c
SRCS := $(wildcard *.c)
# main.o func.o const.o
OBJS := $(SRCS:.c=.o)
# objs/main.o objs/func.o objs/const.o
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
.PHONY : rebuild clean all
$(TARGET) : $(DIRS) $(OBJS)
$(CC) -o $@ $(OBJS)
@echo "Target File ==> $@"
$(DIRS) :
$(MKDIR) $@
$(DIR_OBJS)/%.o : %.c
ifeq ($(DEBUG),true)
$(CC) -o $@ -g -c $^
else
$(CC) -o $@ -c $^
endif
rebuild : clean all
all : $(TARGET)
clean :
$(RM) $(DIRS)
我们来看看编译效果
我们看到已经正确执行了,在当前目录下自动生成两个文件夹 objs target。在 objs 文件夹里生成三个 .o 文件,在 target 文件夹中生成 hello-makefile.out 文件,执行这个可执行文件,结果也是我们之前定义的。下来我们来看看能不能定义 DEBUG 版的程序,这时便要用到一个命令了 objdump -S target,它用于来查看程序是否为调试版。下来我们来看看结果,图 a 为普通版的,图 b 为 DEBUG 版的
图 a 普通版
图 b DEBUG 版
我们看到 DEBUG 版本相对于普通版来说,多了一些东西,比如我们在里面写的 printf 语句,而且多了函数调用的语句。普通版则是只执行程序就 OK 了。通过今天的综合示例的编写,总结如下:1、目录是可以成为目标的依赖的,在规则中创建目录;2、预定义函数是 makefile实战时不可或缺的部分;3、规则中的模式匹配可以直接针对目录中的文件;4、可以使用命令行变量编译特殊的目标版本。
欢迎大家一起来学习 makefile 语言,可以加我QQ:243343083。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。