• makefile 自动生成依赖关系-笔记


    自动生成依赖关系

    拿去直接用?建议仔细看看,因为有些隐含规则的使用可能导致在你的项目中无法正常运行

    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/
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    利用隐含规则,这个其实可以简化为

    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/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    其中利用的隐含规则为

    • %.o自动使用%.c通过 ( C C ) 和 (CC)和 (CC)(CFLAGS)生成
    • 自动搜索VPATH中的头文件和源文件

    对下面的语句做详细解释

    $(DEPS):%.d:%.c
        @$(CC) -MM $(CFLAGS) $< -MT $(patsubst %.c,%.o,$<) -MF $@
    
    • 1
    • 2
    • $(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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • -MF $@: -MF就是指定输出的文件名,这里的$@是一个.d文件

    "VPATH"特性:

    makefile的内置变量,通过VPATH可以指定依赖文件的搜索路径,当规则的依赖文件在当前目录不存在时,make 会在此变量所指定的目录下去寻找这些依赖文件。通常我们都是用此变量来指定规则的依赖文件的搜索路径。其实“ VPATH”变量所指定的是 Makefile中所有文件的搜索路径,包括了规则的依赖文件和目标文件。

    make 搜索目录的顺序是按照变量“ VPATH”定义中的目录顺序进行的(当前目录永远是第一搜索目录)

    makefile的打印信息

    可以用来打印makefile执行过程中的各个变量值

    $(error $(XXX))
    
    $(warning $(XXX))
    
    $(info $(XXX))
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    echart扩展插件词云echarts-wordcloud
    安装linux操作系统
    虚幻5框架GamePlay全图
    Java进阶之路——从初级程序员到架构师,从小工到专家
    【云原生&Docker基础篇第4篇】实战探究Docker数据卷的奥秘
    C++学习之强制类型转换
    位域(位段)/枚举常量用法官方库例程
    java培训技术ModelAttribute注解修饰POJO类型的入参
    K8S群集调度
    什么是Jmeter?Jmeter使用的原理步骤是什么?
  • 原文地址:https://blog.csdn.net/qq_24276421/article/details/126538949