ffmeg 中fftools/Makefile 分析

 1 AVPROGS-$(CONFIG_FFMPEG)   += ffmpeg
  2 AVPROGS-$(CONFIG_FFPLAY)   += ffplay
  3 AVPROGS-$(CONFIG_FFPROBE)  += ffprobe
  4 
  5 AVPROGS     := $(AVPROGS-yes:%=%$(PROGSSUF)$(EXESUF))
  6 PROGS       += $(AVPROGS)
  7 
  8 AVBASENAMES  = ffmpeg ffplay ffprobe
  9 ALLAVPROGS   = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
 10 ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
 11 
 12 OBJS-ffmpeg                        += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o
 13 OBJS-ffmpeg-$(CONFIG_LIBMFX)       += fftools/ffmpeg_qsv.o
 14 ifndef CONFIG_VIDEOTOOLBOX
 15 OBJS-ffmpeg-$(CONFIG_VDA)          += fftools/ffmpeg_videotoolbox.o
 16 endif
 17 OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.o
 18 
 19 define DOFFTOOL
 20 OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes)
 21 $(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
 22 $$(OBJS-$(1)): | fftools
 23 $$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))
 24 $(1)$(PROGSSUF)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
 25 $(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
 26 -include $$(OBJS-$(1):.o=.d)
 27 endef
 28 
 29 $(foreach P,$(AVPROGS-yes),$(eval $(call DOFFTOOL,$(P))))
 30 
 31 all: $(AVPROGS)
 32 
 33 fftools/ffprobe.o fftools/cmdutils.o: libavutil/ffversion.h | fftools
 34 OUTDIRS += fftools
 35 
 36 ifdef AVPROGS
 37 install: install-progs install-data
 38 endif
 39 
 40 install-progs-yes:
 41 install-progs-$(CONFIG_SHARED): install-libs
 42 
 43 install-progs: install-progs-yes $(AVPROGS)
 44     $(Q)mkdir -p "$(BINDIR)"
 45     $(INSTALL) -c -m 755 $(AVPROGS) "$(BINDIR)"
 46 
 47 uninstall: uninstall-progs
 48 
 49 uninstall-progs:
 50     $(RM) $(addprefix "$(BINDIR)/", $(ALLAVPROGS))
 51 
 52 clean::
 53     $(RM) $(ALLAVPROGS) $(ALLAVPROGS_G) $(CLEANSUFFIXES:%=fftools/%)
~                                                                                                                                                                                                          
                                                                                                                                                                                         

分析此文件的目的是为了提高make在项目管理中的使用.
这个文件只是一个局部的Makefile, 并不能单独工作,欲工作需在顶层执行make,欲再次看到变化你可以
touch ./fftools/cmdutils.c , 这是一个基础文件,会引起重新编译。
分析开始:
1. AVPROGS-$(CONFIG_FFMPEG)   += ffmpeg
2. AVPROGS-$(CONFIG_FFPLAY)   += ffplay
3. AVPROGS-$(CONFIG_FFPROBE)  += ffprobe

# makefile (从“fftools/Makefile”,行 3)
AVPROGS-yes = ffmpeg ffplay ffprobe
被赋值的变量都是要立即求值的,
其中CONFIG_FFMPEG,CONFIG_FFPLAY,CONFIG_FFPROBE 均在config.mak有定义为yes
所以到第3行时:
AVPROGS-yes = ffmpeg ffplay ffprobe


5. AVPROGS     := $(AVPROGS-yes:%=%$(PROGSSUF)$(EXESUF))
6. PROGS       += $(AVPROGS)
7.
8. AVBASENAMES  = ffmpeg ffplay ffprobe
9. ALLAVPROGS   = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
10.ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))

# makefile (从“fftools/Makefile”,行 5)
AVPROGS := ffmpeg ffplay ffprobe
对AVPROGS 立即赋值, 结果类型为简单变量,
由于PROGSSUF,EXESUB在config.mak中均定义为空,所以替换结果未变,

PROGS 是一个递归变量,原来它为空值,此时会为以上3值,但随后它还会变
在doc/example/Makefile 第29行
PROGS          += $(EXAMPLES)
所以PROGS 变量在数据库中记录的是
# makefile (从“ doc/examples/Makefile ”,行 29)
PROGS = $(AVPROGS) $(EXAMPLES)
在本文件中的作用是中间过程,被合并到(+=)后续中去了.
递归变量在用的时候会被递归展开.


# makefile (从“fftools/Makefile”,行 8), 说明后面再没有重新赋值了。
AVBASENAMES = ffmpeg ffplay ffprobe
# makefile (从“fftools/Makefile”,行 9), 变量要滞后展开,所以就保持原样了.
ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
# makefile (从“fftools/Makefile”,行 10)
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))

这三行被直接记录到数据库,留着将来使用递归展开.


12 OBJS-ffmpeg                        += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o
13 OBJS-ffmpeg-$(CONFIG_LIBMFX)       += fftools/ffmpeg_qsv.o
14 ifndef CONFIG_VIDEOTOOLBOX
15 OBJS-ffmpeg-$(CONFIG_VDA)          += fftools/ffmpeg_videotoolbox.o
16 endif
17 OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.FFLIBSo

从数据库中看,只记录了17行和29行
# makefile (从“fftools/Makefile”,行 17)
OBJS-ffmpeg- = fftools/ffmpeg_qsv.o fftools/ffmpeg_videotoolbox.o fftools/ffmpeg_videotoolbox.o
从这句话可以看出, $(CONFIG_LIBMFX),$(CONFIG_VDA),$(CONFIG_VIDEOTOOLBOX)为空
# makefile (从“fftools/Makefile”,行 29)
OBJS-ffmpeg = fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o
从这句话可以看出, 第12行等只是一个中间过程,到29行还有赋值

下面命令包要登场,还包括一个循环语句和eval函数,及命令包调用
19 define DOFFTOOL
20 OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes)
21 $(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
22 $$(OBJS-$(1)): | fftools
23 $$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))
24 $(1)$(PROGSSUF)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
25 $(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
26 -include $$(OBJS-$(1):.o=.d)
27 endef
28
29 $(foreach P,$(AVPROGS-yes),$(eval $(call DOFFTOOL,$(P))))

命令包就是自定义函数, makefile中的自定义函数没有返回值,只是过程.

$$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))

这句话我反复研究后, 冒号:后面跟+号这种使用方法,并不是定义一个目标依赖, 而是定义一个当生成该目标时,CFLAGS 变量要添加一点东西. 可以认为这里的: 是限定范围的意思!

插曲:
变量和函数的定义可以用下表来概括。
     IMMEDIATE = DEFERRED
     IMMEDIATE ?= DEFERRED
     IMMEDIATE := IMMEDIATE
     IMMEDIATE ::= IMMEDIATE
     IMMEDIATE += DEFERRED or IMMEDIATE
     IMMEDIATE != IMMEDIATE

     define IMMEDIATE
       DEFERRED
     endef

     define IMMEDIATE =
       DEFERRED
     endef

     define IMMEDIATE ?=
       DEFERRED
     endef

     define IMMEDIATE :=
       IMMEDIATE
     endef

     define IMMEDIATE ::=
       IMMEDIATE
     endef

     define IMMEDIATE +=
       DEFERRED or IMMEDIATE
     endef

     define IMMEDIATE !=
       IMMEDIATE
     endef

由此看出, 函数名称是要被立即求值的,但函数体我们定义的是延时求值.
DOFFTOOL 命令包, 在数据库中是这样定义的.


# makefile (从“fftools/Makefile”,行 19)
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes)
$(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
$$(OBJS-$(1)): | fftools
$$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))
$(1)$(PROGSSUF)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
$(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
-include $$(OBJS-$(1):.o=.d)
endef

可见它就是一个原样照印保留着,留待使用时扩展.
包含了OBJS-$(1) 变量
还定义了一些变量依赖,比较复杂的是还包含了一个.d依赖,这个.d依赖可能会是一个列表,根据OBJ-$(1)文件个数
所以看起来就很复杂了,已经不能用眼睛看透,也不用看了,但可用心体会。
关键是使用这个函数,第29行
对每一个AVPROGS要循环执行 $(call DOFFTOOL,$(P))))
相当于一大堆代码在29行被展开,$(eval)是求值的意思,把它们当作make语句在这里被source进来。
我们直接看看数据库记录的结果吧. 当然是被我整理过的, 不过可以跟宏对的上

# makefile (从“fftools/Makefile”,行 29)
//特定的flags
fftools/ffmpeg_opt.o: CFLAGS +=
fftools/ffmpeg_filter.o: CFLAGS +=
fftools/ffprobe.o: CFLAGS +=
fftools/cmdutils.o: CFLAGS +=  -D_REENTRANT -I/usr/include/SDL2
ffmpeg_g: LDFLAGS +=
ffmpeg_g: FF_EXTRALIBS +=
//objs 组成
OBJS-ffprobe = fftools/cmdutils.o fftools/ffprobe.o
OBJS-ffplay = fftools/cmdutils.o fftools/ffplay.o
OBJS-ffmpeg = fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o
//执行文件的依赖关系
ffmpeg_g: fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o
//.o 的依赖关系
fftools/ffmpeg_opt.o: fftools/ffmpeg_opt.c fftools/ffmpeg_opt.c fftools/ffmpeg.h config.h fftools/cmdutils.h .....
fftools/ffmpeg_filter.o: fftools/ffmpeg_filter.c fftools/ffmpeg_filter.c fftools/ffmpeg.h config.h fftools/cmdutils.h ...
fftools/ffprobe.o: fftools/ffprobe.c config.h libavutil/ffversion.h libavformat/avformat.h libavcodec/avcodec.h ...
fftools/cmdutils.o: fftools/cmdutils.c fftools/cmdutils.c config.h compat/va_copy.h libavformat/avformat.h ...
我们看得很清楚,定义了针对性的FLAGS, OBJS, 及其依赖关系(由.d文件得到)

再往后面看,就已经很简单了,定义了几条规则,这里就忽略不题了。仅说一下关键点

1. fftools/ffprobe.o fftools/cmdutils.o: libavutil/ffversion.h | fftools

多目标依赖右边有一个| 是什么意思?
没有bar |是一个正常的依赖, 有bar 是 bar依赖,
正常依赖是当目标不存在或依赖比目标新,重建目标
bar依赖是当目标不存在,重建目标,当依赖比目标新,不必重建。
这里的fftools只是一个目录,所以它的依赖性会弱一些,bar依赖就可以了.

bar 依赖就是目录依赖.


2. $(RM) $(ALLAVPROGS) $(ALLAVPROGS_G) $(CLEANSUFFIXES:%=fftools/%)
    看得比较多了变量展开,变量替换又是怎样用的?
插曲:
    foo := a.o b.o c.o
    bar := $(foo:%.o=%.c)
    上面的变量替换等价于patsubst(%.o,%.c,$(foo))
    推荐用这两种方法,
    $(foo:.o=.c) 也可以,为了兼容性,当不如用%更规范。

    上述bar的值 为 a.c b.c c.c

问题:怎样快速知道变量的定义? 其未展开的值及展开后的值, 可添加show-var.mk 文件
问题:怎样快速找到使用的规则

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值