SRS4.0源码分析-configure - 弦外之音

/ 0评 / 1

SRS原理》上架了,深度剖析 SRS 源代码,访问地址:srs.xianwaizhiyin.net


本文采用的 SRS 版本是 4.0-b8 , 下载地址:github


SRS4.0源码分析-CMake 讲了 SRS 在 Clion 里面的调试 中使用的CMake 的逻辑。但是实际编译的时候,通常 使用 configure 跟 makefile。

对于一个 开源项目来说,理解了 configure 跟 makefile ,基本上就理解了这个开源项目的50%。

何时阅读 configure 跟 makefile ?这个问题不好说,我看开源项目,有时候是调试,理解完他的大部分代码逻辑,才开始看 configure 跟 makefile ,因为有些编译逻辑 跟 功能代码 有关。

有时候我是一开始就看 configure 跟 makefile 。


开始 分析 SRS 的 configure 文件。

#!/bin/bash
​
#####################################################################################
# the main output dir, all configure and make output are in this dir.
#####################################################################################
# create the main objs
SRS_WORKDIR="."
SRS_OBJS_DIR="objs"
SRS_OBJS="${SRS_WORKDIR}/${SRS_OBJS_DIR}"
SRS_MAKEFILE="Makefile"
​
# linux shell color support.
RED="\\033[31m"
GREEN="\\033[32m"
YELLOW="\\033[33m"
BLACK="\\033[0m"

上面的代码,是设置各种目录,以及 提示颜色。



#####################################################################################
# parse user options, set the variables like:
# srs features: SRS_SSL/SRS_HLS/SRS_HTTP_CALLBACK/......
# build options: SRS_JOBS
#####################################################################################
# parse options, exit with error when parse options invalid.
. auto/options.sh
​
# setup variables when options parsed.
. auto/setup_variables.sh

上面的代码调用了 两个 shell 脚本,是解析 命令参数的 ,例如 configure --jobs=16jobs 就是命令参数,options.shsetup_variables.sh 是把这个参数解析成 shell 变量

options.shsetup_variables.sh 自行阅读即可,比较简单。SRS 的 命令行参数 parse 比较简单,是直接全匹配字符串,不像 FFmpeg 那么复杂。


# We don't need to cleanup the exists files.
rm -f ${SRS_WORKDIR}/${SRS_MAKEFILE}
​
# create objs
mkdir -p ${SRS_OBJS}/${SRS_PLATFORM}
​
# apply user options.
. auto/depends.sh
​
# the auto generated variables.
. auto/auto_headers.sh

再次 执行 两个 shell 脚本 depends.shauto_headers.sh

先分析一下 depends.sh 的逻辑,不贴代码了,直接说重点。

1,Ubuntu_prepare()Centos_prepare()OSX_prepare()

上面 3 个函数分别 检查相应的操作系统的环境,例如 gcc g++ unzip 等软件有没安装之类的。

2,编译 第三方库 state thread 。

3,安装 cherrypy,HOOK 实现用的 cherrypy

4,编译第三方库 libopus,webrtc 要用 libopus

5,编译 FFmpeg 。

6,编译 第三方库 srt 。

7,编译 测试代码 以及 gperf

综上, depends.sh 这个脚本主要就是编译一些 依赖的 第三方的静态库。

再分析一下 auto_headers.shauto_headers.sh 主要是生成 srs_auto_headers.hpp 头文件,实际上是 把 shell 里面的某些变量 转成 c++ 的宏定义,放进去头文件,例如 SRS_HDS_BOOL


# 40 ~ 50 行
#####################################################################################
# generate Makefile.
#####################################################################################
# ubuntu echo in Makefile cannot display color, use bash instead
SRS_BUILD_SUMMARY="_srs_build_summary.sh"
​
# utest make entry, (cd utest; make)
SrsUtestMakeEntry="@echo -e \"ignore utest for it's disabled\""
if [ $SRS_UTEST = YES ]; then SrsUtestMakeEntry="(cd ${SRS_OBJS_DIR}/${SRS_PLATFORM}/utest && \$(MAKE))"; fi

40 ~ 50 行 是 决定 执 不 执行单元测试。


# 51 ~ 57 行
#####################################################################################
# finger out modules to install.
# where srs module is a dir which contains a config file.
SRS_MODULES=()
__mfiles=`find modules -name "config"` && for __mfile in $__mfiles; do
    SRS_MODULES+=("`dirname $__mfile`")
done

SRS_MODULES=() 是定义一个一维数组,这是 shell 定义数组的语法。

然后是 查找 srs-4.0-b8\trunk\modules 目录下有 config 文件的目录,然后加进去 SRS_MODULES 变量。

在 SRS4.0 里面,主要有 hls-ingestermp4-parse 两个 模块 ,如图:

可以用以下命令 把 SRS_MODULES 打印出来看看。

echo "SRS_MODULES[0] is "${SRS_MODULES[0]}
echo "SRS_MODULES[1] is "${SRS_MODULES[1]}
#退出 shell
exit

# variables for makefile for all modules.
__mphonys="" && __mdefaults="" && __mcleanups="" && __makefiles=""
# add each modules for application
for SRS_MODULE in ${SRS_MODULES[*]}; do
    echo "install module at: $SRS_MODULE"
    . $SRS_MODULE/config
    if [[ $SRS_MODULE_MAKEFILE != "" ]]; then
        __makefiles="$__makefiles $SRS_MODULE_MAKEFILE"
    fi
    if [[ 0 -ne ${#SRS_MODULE_MAIN[@]} ]]; then
        __mphonys="$__mphonys $SRS_MODULE_NAME"
        __mdefaults="$__mdefaults $SRS_MODULE_NAME"
        __mcleanups="$__mcleanups $SRS_MODULE_NAME"
    fi
done

上面的代码 就是 把 模块 目录的 config 文件定义的变量 合并进去 __mphonys__mdefaults 等变量。


#75 ~ 80 行
# generate extra phony for each modules.
cat << END > ${SRS_OBJS}/${SRS_MAKEFILE}
​
.PHONY: $__mphonys
​
END

上面的代码是生成 伪目标 ,写进去 makefile文件,如图:

这里有个重点,shell 里面的 << 输入, 然后 > 输出的语法不太容易理解,他那个输出文件是放在中间的,放在 第一个 END 后面,而不是第二个 END 后面。


写到这里,发现 configure 文件有 大约800行 shell,全部贴出来太浪费空间了,下面有些地方只会讲重点。

# 82 ~ 130 行
#####################################################################################
# build tools or compiler args.
# enable gdb debug
GDBDebug=" -g -O0"
# the warning level.
WarnLevel=" -Wall -Wno-deprecated-declarations"
# the compile standard.
CppStd="-ansi"
if [[ $SRS_CXX11 == YES ]]; then
    CppStd="-std=c++11"
fi
if [[ $SRS_CXX14 == YES ]]; then
    CppStd="-std=c++14"
fi
# performance of gprof
SrsGprof=""; SrsGprofLink=""; if [ $SRS_GPROF = YES ]; then SrsGprof=" -pg -lc_p"; SrsGprofLink=" -pg"; fi
# performance of gperf
SrsGperf=""; SrsGperfLink=""; if [ $SRS_GPERF = YES ]; then SrsGperfLink=" -lpthread"; fi
# the cxx flag generated.
CXXFLAGS="${CXXFLAGS} ${CppStd}${WarnLevel}${GDBDebug}${LibraryCompile}${SrsGprof}"
if [ $SRS_GPERF = YES ]; then
    CXXFLAGS="${CXXFLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free";
fi
# For coverage.
if [[ $SRS_GCOV == YES ]]; then
    SrsGcov="-fprofile-arcs -ftest-coverage"
fi
if [[ $SRS_GCOV == YES ]]; then
    CXXFLAGS="${CXXFLAGS} ${SrsGcov}";
fi
# User configed options.
if [[ $SRS_EXTRA_FLAGS != '' ]]; then
    CXXFLAGS="${CXXFLAGS} $SRS_EXTRA_FLAGS";
fi
# Start to generate the Makefile.
cat << END >> ${SRS_OBJS}/${SRS_MAKEFILE}
GCC = ${SRS_TOOL_CC}
CXX = ${SRS_TOOL_CXX}
AR = ${SRS_TOOL_AR}
LINK = ${SRS_TOOL_CXX}
CXXFLAGS = ${CXXFLAGS}
​
.PHONY: default srs srs_ingest_hls
​
default:
​
END

上面的代码 主要是指定编译选项, 有几个 重点

1,指定 编译选项 调试级别(GDBDebug),警告(WarnLevel),C++标准(CppStd)

2,使用 Gprof 或者 Gperf 做性能分析,

推荐阅读 《Gprof 性能分析》《Gperf 性能分析》

最后就是 输出这些变量到 makefile 文件。


130 ~ 197 行 主要是 赋值 SrsLinkOptions 变量,link 选项,不做分析。


从 200 行 sehll 代码开始,就是重点了,主要是 编译 SRS自身 的模块代码。

# 198 ~ 342 行
#####################################################################################
# Modules, compile each module, then link to binary
#
#Core, depends only on system apis.
MODULE_ID="CORE"
MODULE_DEPENDS=()
ModuleLibIncs=(${SRS_OBJS_DIR})
MODULE_FILES=("srs_core" "srs_core_version4" "srs_core_autofree" "srs_core_performance"
  "srs_core_time")
CORE_INCS="src/core"; MODULE_DIR=${CORE_INCS} . auto/modules.sh
CORE_OBJS="${MODULE_OBJS[@]}"
# 后续代码逻辑类似,省略....

上面的代码主要有一个重点 ,就是执行 auto/modules.sh 来生成 模块代码的 makefile文件。

MODULE_DIR=${CORE_INCS} . auto/modules.sh 这句 shell 命令,我也不太明白,中间的 . 是什么意思,埋个坑,后面填。

补充: shell 的语法是 用 空格 或者 ; 隔开不同的命令。

所以上面 是两个命令。

  1. MODULE_DIR=${CORE_INCS}
  2. . auto/modules.sh

前面的 .source 命令的另一种写法,推荐阅读《Linux下source命令详解》

INCS 是 includes 的缩写,头文件包含路径。

后面的 210 ~ 252 行代码,都是 类似的 逻辑,生成 模块代码的 makefile文件。

总结一下,SRS 自身有 4 个模块,分别是。

  1. CORE 应该是核心模块
  2. KERNEL 应该是内核模块
  3. PROTOCOL 应该是协议模块
  4. SRT 这个模块应该是 对 libsrt 库的封装
  5. app 功能封装模块,集群,回源之类的功能。
  6. servermain 模块,configure里面把这两个分成独立的 modules ,但是可以直接理解为 main 入口就行。

这 6 个模块都有各自的文件夹,如图:


继续 分析 configure (shell脚本)

343 ~ 438 行 应该是 为了 link 出来 srs 可执行文件,做一些变量赋值的准备工作,库依赖定义之类的。


# 439 ~ 449 行
#####################################################################################
# generate colorful summary script
. auto/summary.sh
​
#####################################################################################
# makefile
echo "Generate Makefile"
​
# backup old makefile.
rm -f ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk &&
mv ${SRS_WORKDIR}/${SRS_MAKEFILE} ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk

又有一个 . ,这个还是 source 命令的缩写, summary.sh 是打印总结信息。然后 把 makefile 重命名成 makefile.bk 。


449 行 后面的逻辑 主要有是以下2点。

1,把之前的 shell 变量,丢进去 生成 makefile 文件。

2,创建各种目录,为 make 跟 运行 srs做准备。


configure shell 脚本分析完毕,不过还有一个 重点, configure 会生成两个 makefile 文件,trunck/Makefiletrunck/objs/Makefile

trunck/Makefile 是主 makefile, objs 目录下的应该是被 trunck/Makefile 引入的。

trunck/Makefile 里面的规则应该会用到 trunck/objs/Makefile

makefile 的编译逻辑,请看 《SRS4.0源码分析-makefile》


©版权所属:知识星球:弦外之音,QQ:2338195090。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注