静态编译ffmpeg
这两天折腾了一下完全静态编译ffmpeg,期望通过这种方式实现编译出来的ffmpeg能够在各个linux发现版上运行。进而可以延伸到编译出来完全静态的依赖ffmpeg库的应用程序,从而简化产品在各个linux发行版的产品编译和部署区分,减少开发和维护成本。
经过尝试,最终确实编译出来完全静态的ffmpeg,但是也发现了隐患,具体在"一些问题"中描述。所以,我对完全静态编译持保留意见,需要根据实际的使用情况来定。下面的文字,就是我整理的本次尝试的要点了。
1. 静态编译
首先,查看一下之前编译出来的ffmpeg的动态库链接情况。可以看出它链接了许多动态库,这些库有些是系统自带的,有的需要自己安装。
[root@root tmp]# ldd ffmpeg
linux-vdso.so.1 => (0x00007fff133fe000)
libm.so.6 => /lib64/libm.so.6 (0x00007fb094f81000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fb094d65000)
librt.so.1 => /lib64/librt.so.1 (0x00007fb094b5c000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fb094958000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fb094650000)
libnuma.so.1 => /lib64/libnuma.so.1 (0x00007fb094444000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fb09421f000)
libbz2.so.1 => /lib64/libbz2.so.1 (0x00007fb09400f000)
libz.so.1 => /lib64/libz.so.1 (0x00007fb093df8000)
libc.so.6 => /lib64/libc.so.6 (0x00007fb093a36000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb09528c000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fb093820000)
而完全静态的ffmepg是这样的:
[root@root tmp]# ldd ffmpeg
not a dynamic executable
下面就是静态编译的要点,具体可以参考文档结尾附的编译脚本内容。
1.1 安装标准静态库
安装linux c标准库: yum install glibc-static
安装stdc++静态库: yum install libstdc++-static
1.2 编译第三方静态库
ffmpeg通常会使用一些第三方库,例如: x264, x265, libfdk-aac等。这些第三方库通常都是可以通过configure配置(--enable-static=yes --enable-shared=no)控制产生静态库,不创建动态库。对于一些没有configure的库,其实也是有编译出静态库的方法,注意发现就OK。该过程的编译脚本,可以参考文后附的编译脚本内容。
1.3 编译静态ffmpeg
具体的configure配置,可以参考附的编译脚本内容。
2. 一些问题
在编译过程中遇到的大部分问题都是链接库出错,对于这种问题,基本就是安装或编译需要的静态库,偶尔也可能是库的顺序问题。
不过,在尝试编译支持nvenc的时候,出现了warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking警示信息,因为已经编译出静态文件,所以当时并没有在意。不过在后来的测试中,发现在使用nvenc环境进行nvenc编解码操作的的时候,程序会段错误。原来,像"dlopen"这样的函数,是依赖运行环境的,需要使用运行环境的动态库。故,完全静态编译存在这样的隐患,就是有些函数依赖运行环境的动态库(其实这些库本身也是为了兼容性,不同平台提供相同的接口),所以,标准库除非要求,否则尽量使用动态库吧。
3. 附静态ffmpeg下载
ffmpeg: http://pan.baidu.com/s/1kVfOY7H
ffprobe: http://pan.baidu.com/s/1boS8cJt</