FFmpeg源码学习笔记:Makefile是怎么组织编译过程的

本文概述了FFmpeg源码Makefile的关键点,包括.c文件编译为.o文件、.o文件转换为动态库.so或静态库.a,以及ffmpeg可执行文件的生成过程,通过实例和资源推荐加深理解。
摘要由CSDN通过智能技术生成


前言

在上一篇博客《FFmpeg源码编译—支持x264编码》中,通过简单的配置、编译、安装等几个步骤,就完成了FFmepg源码的编译。本文总结下Makefile是怎么组织整个编译过程的,也加深下自己的印象。


一、Makefile基础

这方面资料比较多,简单罗列下我感觉还不错的资料。
1、陈皓老师的《跟我一起写Makefile》
Github上有大佬重新进行了排版,看起来比较舒服,详见:跟我一起写Makefile (PDF重制版)
2、GNU官网资料
这是第一手资料,就是看英文比较劝退,新手别轻易尝试,详见:GNU make
3、某未来大佬博客
高度模拟了FFmpeg源码Makefile编译的过程,比如动态库、静态库生成的方式等,详见:Makefile学习笔记:静态库和动态库的生成和使用

二、FFmpeg源码makefile几个关键点

查看ffmpeg_build中的编译产物,可见有很多东东,下面节选了一些关键部分,bin目录中的可执行文件,以及lib目录中的动态库.so文件。还有个很重要的include目录,内容太多就不列出来了。

├── bin
│   ├── ffmpeg
│   └── ffprobe
├── lib
│   ├── libavcodec.so -> libavcodec.so.60.31.102
│   ├── libavcodec.so.60 -> libavcodec.so.60.31.102
│   ├── libavcodec.so.60.31.102
│   ├── libavdevice.so -> libavdevice.so.60.3.100
│   ├── libavdevice.so.60 -> libavdevice.so.60.3.100
│   ├── libavdevice.so.60.3.100
│   ├── libavfilter.so -> libavfilter.so.9.12.100
│   ├── libavfilter.so.9 -> libavfilter.so.9.12.100
│   ├── libavfilter.so.9.12.100
│   ├── libavformat.so -> libavformat.so.60.16.100
│   ├── libavformat.so.60 -> libavformat.so.60.16.100
│   ├── libavformat.so.60.16.100
│   ├── libavutil.so -> libavutil.so.58.29.100
│   ├── libavutil.so.58 -> libavutil.so.58.29.100
│   ├── libavutil.so.58.29.100
│   ├── libpostproc.so -> libpostproc.so.57.3.100
│   ├── libpostproc.so.57 -> libpostproc.so.57.3.100
│   ├── libpostproc.so.57.3.100
│   ├── libswresample.so -> libswresample.so.4.12.100
│   ├── libswresample.so.4 -> libswresample.so.4.12.100
│   ├── libswresample.so.4.12.100
│   ├── libswscale.so -> libswscale.so.7.5.100
│   ├── libswscale.so.7 -> libswscale.so.7.5.100
│   ├── libswscale.so.7.5.100

结合前面分享的大佬博客,这里本着自顶向下、逐步细化的原则,尝试找下源码Makefile中几个对应的关键点。

1.源码.c文件是怎么变成.o文件的

代码ffbuild/common.mak文件节选:

define COMPILE
       $(call $(1)DEP,$(1))
       $($(1)) $($(1)FLAGS) $($(2)) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<)
endef

COMPILE_C = $(call COMPILE,CC)

%.o: %.c
	$(COMPILE_C)

毕竟是行业大佬写的,小白看了真的很劝退有木有?但是静下心来分析下,还是能看到一些端倪的。
$(1)是通过call给COMPILE后传入的参数CC,通过ffbuild/config.mak可知,

$($(1))               #CC=gcc
$($(1)_C)             #CC_C=-c
$($(1)_O)             #CC_O=-o $@

2.源码.o文件是怎么变成动态库.so或静态库.a文件的

代码ffbuild/library.mak文件节选:

$(SUBDIR)$(LIBNAME): $(OBJS) $(STLIBOBJS)
	$(RM) $@
	$(AR) $(ARFLAGS) $(AR_O) $^
	$(RANLIB) $@

其中,
目标$(SUBDIR)$(LIBNAME),就是最终的静态库/动态库的名字,如libavcodec.so等

#在ffbuild/config.mak可见库名字是拼接起来的,其中NAME在各库中定义,如libavcodec/Makefile中定义NAME = avcodec
FULLNAME=$(NAME)$(BUILDSUF)
LIBPREF=lib
LIBSUF=.a
LIBNAME=$(LIBPREF)$(FULLNAME)$(LIBSUF)

SLIBPREF=lib
SLIBSUF=.so
SLIBNAME=$(SLIBPREF)$(FULLNAME)$(SLIBSUF)

依赖 $(OBJS)

#在各库如libavcodec/Makefile中定义依赖的.o文件,节选如下
OBJS = ac3_parser.o                                                     \
       adts_parser.o                                                    \
       allcodecs.o                                                      \
       avcodec.o                                                        \
       avdct.o                                                          \

规则$(AR) $(ARFLAGS) $(AR_O) $^

#通过ffbuild/config.mak可知以下信息
$(AR)                  #AR=ar
$(ARFLAGS)             #ARFLAGS=rcD
$(AR_O)                #AR_O=$@,其中$@是自动化变量,表示目标
$^                     #自动化变量,所有的依赖目标的集合

3.源码ffmpeg可执行文件是怎么生成的

代码根目录Makefile文件节选:

#LD=gcc,先编译、链接产生ffmpeg_g文件
%$(PROGSSUF)_g$(EXESUF): $(FF_DEP_LIBS)
	$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS)


#对可执行文件如ffmpeg_g进行strip,生成ffmpeg可执行文件
$(PROGS): %$(PROGSSUF)$(EXESUF): %$(PROGSSUF)_g$(EXESUF)
ifeq ($(STRIPTYPE),direct)
	$(STRIP) -o $@ $<
else
	$(RM) $@
	$(CP) $< $@
	$(STRIP) $@
endif

找到这3个关键点,是不是就跟已知知识联系起来了?


总结

本文只是粗浅的列出了FFmpeg源码Makefile中几个关键的位置,通过对比的方式加深理解。后续还有很多工作要做,比如:
1、编译时具体是怎么决定生成动态库or静态库;
2、几个库如avcodec、avformat等是怎么逐个产生。
当然还有一些细节,等有机会再深究吧。

  • 30
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值