windows系统下mysys,VS2005编译FFmpeg库过程

⌚Time: 2022-05-14 22:20:47

👨‍💻Author: Jack Ge

应该使用vs2013而不是使用vs2005去编译,本文只是记录在编译过程出现的问题和解决办法


安装依赖环境:

msinttypes-r26.zip包括c99的两个头文件inttypes.h,stdint.h,解压到目录"C:\Users\m\Downloads\msinttypes-r26" 由于msvc不支持unix的unistd.h,所以需要自己手动编写一个unistd.h 编辑以下代码,保存为unistd.h,并且同样保存在"C:\Users\m\Downloads\msinttypes-r26"

/*
unistd.h maps(roughly) to io.h

*/
#ifndef _UNISTD_H
#define _UNISTD_H
#include <io.h>
#include <direct.h>
#include <process.h>
#endif //_UNISTD_H

在configure中使用参数-I附加头文件目录"C:\Users\m\Downloads\msinttypes-r26"

解压ffmpeg-2.4.tar.gz到源码目录下,编辑configure文件

        if [ -z "$cl_major_ver" ] || [ $cl_major_ver -ge 18 ]; then
            cc_default="cl"
        else
            cc_default="c99wrap cl"

改为

        if [ -z "$cl_major_ver" ] || [ $cl_major_ver -ge 18 ]; then
            cc_default="c99wrap cl"
        else
            cc_default="c99wrap cl"

否则会有因为不支持c99语法而产生的报错

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\INCLUDE\io.h(224) : 参见“unlink”的声明
消息:“The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _unlink. See online help for details.”
libavformat/hdsenc.c(535) : error C2059: 语法错误 : “{”
libavformat/hdsenc.c(544) : error C2059: 语法错误 : “if”
libavformat/hdsenc.c(546) : error C2143: 语法错误 : 缺少“{”(在“->”的前面)
libavformat/hdsenc.c(546) : error C2059: 语法错误 : “->”
libavformat/hdsenc.c(548) : error C2143: 语法错误 : 缺少“{”(在“->”的前面)
libavformat/hdsenc.c(548) : error C2059: 语法错误 : “->”
libavformat/hdsenc.c(549) : error C2059: 语法错误 : “return”
libavformat/hdsenc.c(550) : error C2059: 语法错误 : “}”
libavformat/hdsenc.c(579) : error C2059: 语法错误 : “.”
libavformat/hdsenc.c(580) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(581) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(582) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(583) : error C2059: 语法错误 : “,”
libavformat/hdsenc.c(587) : error C2059: 语法错误 : “.”
libavformat/hdsenc.c(594) : error C2059: 语法错误 : “.”
make: *** [libavformat/hdsenc.o] Error 2

执行configure时不知道为什么没有检测到msvc,导致$libc_type没有正确赋值,导致编译链接报错,strtod.c、snprintf.c没有得到编译

error LINK2001:undefined reference to '_avpriv__strtod'
error LINK2001:undefined reference to '_avpriv__snprintf'

手动去设置,在configure文件的

case $libc_type in
    bionic)
        add_compat strtod.o strtod=avpriv_strtod
        ;;

之前加上


libc_type_fix(){
pfx=$1
 eval ${pfx}libc_type=msvcrt
        # The MSVC 2010 headers (Win 7.0 SDK) set _WIN32_WINNT to
        # 0x601 by default unless something else is set by the user.
        # This can easily lead to us detecting functions only present
        # in such new versions and producing binaries requiring windows 7.0.
        # Therefore explicitly set the default to XP unless the user has
        # set something else on the command line.
        check_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" ||
            add_${pfx}cppflags -D_WIN32_WINNT=0x0502
}
libc_type_fix

在源码目录下libavformat/os_support.h中,将以下行注释,否则报lseek重定义错误

//#  define lseek(f,p,w) _lseeki64((f), (p), (w))

在compat\msvcrt\snprintf.c中,注释

//#if defined(__MINGW32__)
#define EOVERFLOW EFBIG
//#endif

否则提示

error C2065:"EOVERFLOW";未声明的标识符

compat\windows\makedef文件编辑,将

sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |

改为

sed -e '\/public symbols/,$!d' -e '\/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |

否则sed报错,并且生成的def文件不完整:

sed.exe -e expression #1,char 1:unknow command :`C'

编译时用到User32.lib、Gdi32.lib库,创建库文件夹C:\Users\m\Downloads\lib,加入Gdi32.Lib,并且在configure指定库目录,但是在链接过程出现

LINK: warning LNK4044: 无法识别的选项“/LC:\Users\m\Downloads\lib";已忽略

原因是configure中指定库目录使用-L,这是mingw的用法,而对于msvc,应该是-LIBPATH: 还需要在libavdevice\gdigrab.c中加入以下语句来调用库

#pragma comment  (lib,"User32.lib")
#pragma comment  (lib,"Gdi32.lib")

否则出现以下报错

正在创建库 libavdevice/avdevice.lib 和对象 libavdevice/avdevice.exp
gdigrab.o : error LNK2019: 无法解析的外部符号 __imp__EndPaint@8,该符号在函数 _gdigrab_region_wnd_proc@16 中被引用

对于mysys的启动,需要让其继承msvc的环境变量,才能够使用msvc的link.exe,cl.exe等工具。 首先对于mysys安装目录下的msys.bat文件加入以下内容

call "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat"

寻找以下行,取消注释(去掉rem)

rem setMSYS2_PATH_TYPE=inherit

在开始菜单中,找到vs的目录,启动Visual Studio 2005命令提示,并且在其中运行msys.bat来启动mysys,启动后,在mysys中输入

export PATH=/C/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 8/VC/bin:$PATH

确保vs环境在系统变量前,则优先使用vs的link.exe,而不是mysys的link.exe(与编译链接无关的一个程序)

在mysys中,切换目录

 cd /C/Users/m/Downloads/ffmpeg-2.4.tar/ffmpeg-2.4

执行configure

 ./configure --prefix=build_msvc --toolchain=msvc --enable-shared --disable-static --extra-cflags="-I/C/Users/m/Downloads/msinttypes-r26 -Dsnprintf=_snprintf" --extra-ldflags="-LIBPATH:/C/Users/m/Downloads/lib"

-Dsnprintf=_snprintf 定义宏snprintf=_snprintf,否则提示

error C4013:"snprintf"未定义,假设外部返回int

--enable-shared 是指定生成动态链接库,可以在编程中进行使用,否则编译出来只有单个的ffmpeg程序

若configure出现以下提示

c99wrap cl is unable to create an executable file.
If c99wrap cl is a cross-compiler, use the --enable-cross-compile option.
Only do this if you know what cross compiling means.
C compiler test failed.

检查c99conv.exe、c99wrap.exe是否安装正确

configure会生成config.mak、config.h文件,编辑config.h 做如下修改,将0改为1

#define HAVE_IO_H 1
#define HAVE_UNISTD_H 1

否则源文件不能相应头文件,导致提示

error C4013:"read"未定义,假设外部返回int
error C4013:"write"未定义,假设外部返回int
error C4013:"_lseeki64"未定义,假设外部返回int
error C4013:"close"未定义,假设外部返回int

编译安装

make
make install

若出现以下错误

CC      libavdevice/alldevices.o
make: *** [libavdevice/alldevices.o] Error 1

检查configure配置附加头文件目录是否正确,inttypes.h,stdint.h头文件是否在相应目录中

使用mysys2编译时,出现下面两个问题,使用mysys1.0.11可以避免

awk: 命令行:1: /including/ { sub(/^.*file: */, ""); gsub(/\/, "/"); if (!match($0, / /)) print "libavdevice/alldevices.o:", $0}
awk: 命令行:1:                                                                                                           ^ 未结束的字符串

只能将condig.mak文件以下部分注释

#CCDEP=$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0}' > $(@:.o=.d)

而编译执行./compat/windows/makedef时mysys2由于参数过长,竟然不能解析所有输入的参数 问题就出在这里

for object in "$@"; do
    if [ ! -f "$object" ]; then
        echo "Object does not exist: ${object}" >&2
        exit 1
    fi
done

提示

Object does not exist: liba

对于makedef的参数,包含几百上千个.o文件名字,但是到libavcodec/mpegutils.o之后就截止了,后面就因为参数过长直接被舍弃,导致出现错误。而使用mysys1.0.11却可以编译通过 编译后的文件在build_msvc的bin目录下


总结: