通过分析makefile编译构建过程,梳理各个具体目录的作用和联系

这是一张freewind画的结构图,个人通过分析查看跟踪makefile整理,使用vlc版本为3.0.6 for linux

ubuntu 18.04编译,默认配置。

为了方便查看已经缩减了很多具体的细节,后续文字补充;

vlc源码移植到Androidstudio vlc源码分析_动态库

上图说明:

vlc 顶层的makefile, 会进入各个子目录中查找makefile 执行编译子文件夹中的makefile:

compat目录:会编译出 libcompat.la  底层和具体系统 交互的库,不同平台在这里区分。 这是一个用作兼容不同平台的库。

src目录:libvlccore.la  vlc核心模块,比如输入主线程等 核心功能的实现。

module目录: 各个插件模块, 会得到多个动态库,vlc 运行时根据不同的文件需要动态的加载这些插件。

lib目录: libvlc.la 外层调用,一些接口api包装。

bin目录:vlc  cvlc  编译出来的应用程序

这些目录的编译是有依赖关系的,如图箭头。 vlc 可执行程序,要用到 libvlc.la  而libvlc.la 是一些接口封装,它需要 libvlccore.la 核心功能,compat作为一些平台差异的基础库。 至于module编译出来的动态库,只有在vlc程序运行的时候,比如要播放一个mp4文件,就需要一个moudle目录下的libmp4库,这个时候回动态加载libmp4作为 demuxer解复用器使用。 (这些库都安照vlc的框架实现了对应的接口)

 

 

分析过程中碰到的一些疑惑,记录下:

================20190827补充=======================================================

补充一些笔记:

make 命令有一些选项,有助于理解makefile  其中一个选项 

#make -n 或者 #make --just-print  // 仅仅打印要执行的命令。

很好用,比如在 /module 目录下分析 编译mp4的demux模块。

#make libmp4_plugin.la -n

vlc源码移植到Androidstudio vlc源码分析_html_02

如果提示已经是最新,找其中相关的一个文件加个空格改动一下即可。如上图,打印了两遍命令,第一遍只是一些makefile 中的变量都替换了,第二遍连一些shell变量和语法都替换了,可以看到完整的编译命令。相比之下默认的make则隐藏了这些命令。

==================================================================================

1.0 vlc 顶层目录下的makefile , 查看 all:目标规则,

all:

    $(MAKE) $(AM_MAKEFLAGS) all-recursive

相当于make all-recursive, 可是直接找 all-recursive: 可能找不到这个target的依赖规则,但是能看到

RECURSIVE_TARGETS = all-recursive....   

am__recursive_targets=$(RECURSIVE_TARGETS) ....

am__recursive_targets 这个target是有对应规则的,把对应变量展开,就能看到其实是多个target对应一条规则的用法。即

====================================================================
$(am__recursive_targets):
    #这里是编译命令......

=====================================================================

am__recursive_targets = \
  $(RECURSIVE_TARGETS) \
  $(RECURSIVE_CLEAN_TARGETS) \
  $(am__extra_recursive_targets)
======================================================================

RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
	ctags-recursive dvi-recursive html-recursive info-recursive \
	install-data-recursive install-dvi-recursive \
	install-exec-recursive install-html-recursive \
	install-info-recursive install-pdf-recursive \
	install-ps-recursive install-recursive installcheck-recursive \
	installdirs-recursive pdf-recursive ps-recursive \
	tags-recursive uninstall-recursive


=********************************************************************=

$(am__recursive_targets)展开后:
all-recursive check-recursive cscopelist-recursive ......:
    #这里是编译命令......

 

2.0 $(am__recursive_targets): 的规则中执行的命令中,调用的shell 脚本执行,

保证在一个线程中执行shell脚本的命令,所有的命令都在一行中完成,这与makefile的作用机制有关

要调用shell里面的变量使用$$

 

3.0 对于一些变量值,可以在编译的时候使用 echo 输出,方便分析

4.0 分析一个具体的编译文件命令:以src目录下makefile为例,追踪依赖关系,最后落实到具体的 .c 文件编译到 .lo 文件

 

 

vlc源码移植到Androidstudio vlc源码分析_依赖关系_03

echo上面的几个变量,$(LTCOMPILE):

../doltcompile gcc -DHAVE_CONFIG_H -I. -I.. -DMODULE_STRING="core" -DLOCALEDIR="/usr/local/share/locale" -DPKGDATADIR="/usr/local/share/vlc" -DPKGLIBDIR="/usr/local/lib/vlc" -DHAVE_DYNAMIC_PLUGINS -I../include -I../include -g -O2 -Wall -Wextra -Wsign-compare -Wundef -Wpointer-arith -Wvolatile-register-var -Wformat -Wformat-security -Wbad-function-cast -Wwrite-strings -Wmissing-prototypes -Werror-implicit-function-declaration -Winit-self -Wlogical-op -Wshadow=local -pipe -fvisibility=hidden -O3 -fno-math-errno -funsafe-math-optimizations -fno-rounding-math -fno-signaling-nans -fcx-limited-range -funroll-loops -fomit-frame-pointer -fstack-protector-strong
 

第二行命令展开,即对应实际的编译命令

<== ../doltcompile gcc .... -MT $@ -MD -MP .deps -c -o $@ $<

<== gcc XX.lo -c -o XX.lo XX.c

 

 

再简化一下这个图(实在是难看)

 

vlc源码移植到Androidstudio vlc源码分析_依赖关系_04