拿去直接用?建议仔细看看,因为有些隐含规则的使用可能导致在你的项目中无法正常运行
MODULE = livestream
TAR = lib${MODULE}.a
#获取所有的.c .o .d列表
SUB_DIRS += ./udp
SUB_DIRS += ./http
SUB_DIRS += ./srt
SUB_DIRS += ./rtmp
SUB_DIRS += ./hls
VPATH= $(SUB_DIRS) .
CFLAGS += $(foreach dir,$(VPATH),-I$(dir))
CSRCS=$(foreach dir,$(VPATH),$(wildcard $(dir)/*.c))
# CSRCS 中所有的.c替换成.o
OBJS=$(CSRCS:.c=.o)
# OBJS 中所有的.o替换成.d
DEPS=$(OBJS:.o=.d)
# $(info CSRCS=$(CSRCS))
# $(info OBJS =$(OBJS))
# $(info DEPS =$(DEPS))
# $(info CFLAGS =$(CFLAGS))
############################### build ###############################
all: ${TAR}
$(TAR):$(OBJS)
@printf "CC -o $@\n"
@${AR} -r ${TAR} $(OBJS)
@cp ${TAR} ../libs/
# 下面的可以不用,因为隐含规则里有.c生成.o的规则,替换makefile内置的CFLAGS变量可以控制这一隐含规则执行时的参数
# 同时因为我们用了-include $(DEPS),在.d文件展开时,也会包括一个.o:.c的过程
# 不定义下面的过程的话,编译过程会被打印出来,除非将$(CC)替换成一个不打印的
$(OBJS):%.o:%.c
@$(CC) -o $@ -c $< $(CFLAGS)
@printf "CC -o $@\n"
$(DEPS):%.d:%.c
@$(CC) -MM $(CFLAGS) $< -MT $(patsubst %.c,%.o,$<) -MF $@
# 将所有的.d文件包含进来,
-include $(DEPS)
.PHONY:clean install
clean:
$(RM) $(TAR) $(OBJS) $(DEPS)
install:
@cp ${TAR} ../libs/
利用隐含规则,这个其实可以简化为
SUB_DIRS += ./udp
SUB_DIRS += ./http
SUB_DIRS += ./srt
SUB_DIRS += ./rtmp
SUB_DIRS += ./hls
VPATH= $(SUB_DIRS) .
# 简化版的省略了CFLAGS += $(foreach dir,$(VPATH),-I$(dir)),是利用了VPATH特性
CFLAGS +=
CSRCS=$(foreach dir,$(VPATH),$(wildcard $(dir)/*.c))
OBJS=$(CSRCS:.c=.o)
DEPS=$(OBJS:.o=.d)
############################### build ###############################
all: ${TAR}
$(TAR):$(OBJS)
@${AR} -r ${TAR} $(OBJS)
$(DEPS):%.d:%.c
@$(CC) -MM $(CFLAGS) $< -MT $(patsubst %.c,%.o,$<) -MF $@
-include $(DEPS)
.PHONY:clean install
clean:
$(RM) $(TAR) $(OBJS) $(DEPS)
install:
@cp ${TAR} ../libs/
其中利用的隐含规则为
对下面的语句做详细解释
$(DEPS):%.d:%.c
@$(CC) -MM $(CFLAGS) $< -MT $(patsubst %.c,%.o,$<) -MF $@
$(CC) -MM $(CFLAGS) $< : 利用gcc的-MM参数,将$<(.c文件)中用到的头文件打出来,包括头文件中包含的头文件,-MM不会输出标准库的头文件
-MT $(patsubst %.c,%.o,$<) : 因为默认生成的.d中,目标(.o)不带路径,但是我传进去的$<(.c文件)是带路径,我需要给他替换下,以避免同名源文件导致的目标重定义,生成的.d结果如下
http/http_proto.o: http/http_proto.c http/http_proto.h http/http_curl.h \
http/http.h /home/zhangbin/2022/TVMAN/tvman/app/liveStream/livestream.h \
/home/zhangbin/2022/TVMAN/tvman/common/include/myzlog.h \
/home/zhangbin/2022/TVMAN/tvman/common/include/zlog.h \
/home/zhangbin/2022/TVMAN/tvman/common/include/util.h \
/home/zhangbin/2022/TVMAN/tvman/app/include/common_type.h \
/home/zhangbin/2022/TVMAN/tvman/common/include/key_value.h
-MF $@: -MF就是指定输出的文件名,这里的$@是一个.d文件makefile的内置变量,通过VPATH可以指定依赖文件的搜索路径,当规则的依赖文件在当前目录不存在时,make 会在此变量所指定的目录下去寻找这些依赖文件。通常我们都是用此变量来指定规则的依赖文件的搜索路径。其实“ VPATH”变量所指定的是 Makefile中所有文件的搜索路径,包括了规则的依赖文件和目标文件。
make 搜索目录的顺序是按照变量“ VPATH”定义中的目录顺序进行的(当前目录永远是第一搜索目录)
可以用来打印makefile执行过程中的各个变量值
$(error $(XXX))
$(warning $(XXX))
$(info $(XXX))