通过分析makefile编译构建过程,梳理各个具体目录的作用和联系
这是一张freewind画的结构图,个人通过分析查看跟踪makefile整理,使用vlc版本为3.0.6 for linux
ubuntu 18.04编译,默认配置。
为了方便查看已经缩减了很多具体的细节,后续文字补充;
上图说明:
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
如果提示已经是最新,找其中相关的一个文件加个空格改动一下即可。如上图,打印了两遍命令,第一遍只是一些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 文件
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
再简化一下这个图(实在是难看)