iOS编译ffmpeg支持smb问题ERROR: libsmbc
引子
需求是在iOS上播放smb中的视频,不想使用VLCMobileKit,所以考虑ffmpeg
但找了一圈,可以直接拿来用的只有一个CYPlayer,封装的挺好,但不太合适。所以想自行编译FFMpeg并支持smb。
FFmpeg是支持smb协议的,但编译时需要提前准备好smb的库文件等。
smb库文件也可以自己编译,大多数都是基于kxsmb编译的。这里我直接找来线程的smb库直接用了。
关于ffmpeg的编译教程也挺多,参考以下:
https://zhuanlan.zhihu.com/p/615573274
https://www.cnblogs.com/machao/p/5385689.html
想在ffmepg中支持smb,在执行 ./configure时,添加以下参数
--enable-libsmbclient --enable-gpl --enable-version3
这样ffmepg就支持smb了
编译遇到的问题:
兴高采烈的执行编译了。结果报错: libsmbclient not found
错误原因
没有指定smb的库路径以及头文件的路径

如何指定头文件以及lib路径?
依然是在执行./configure命令时,后面跟参数:
--extra-ldflags 指定lib目录以及链接库文件
--extra-cflags 指定头文件目录
示例:
--extra-ldflags="-Lxxxpath -lxxxb“ 指定库路径xxxpath,链接库libxxxb.a
--extra-cflags="-Ixxxxheader" 指定头文件路径xxxxheader
实际上我的(是一段脚本)
SMB_HEADERS="/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient/libsmbclient"
SMB_LIBS="/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient"
FFMPEG_CFLAGS="$FFMPEG_CFLAGS -I${SMB_HEADERS}"
FFMPEG_DEP_LIBS="$FFMPEG_DEP_LIBS -L${SMB_LIBS} -lsmbclient -ltalloc -ltdb -ltevent -lwbclient"
执行时就是如下:
--extra-ldflags="-L/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient -lsmbclient -ltalloc -ltdb -ltevent -lwbclient"
--extra-cflags="-I/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient/libsmbclient"
这就指定了smb库和头文件的路径,同时链接了所有的库。
这里注意:
-L是指定库路径,-I(大写的i)是指定头文件路径,-l(小写的le)是链接静态库
例如 -ltevent 就是链接libevent.a的库,注意实际文件名是lib开头,链接时省去lib了
开开心心再去编译。又报了同样的错误。
再次遇到libsmbclient not found
很懵逼,该检查的都检查了,路径都没问题。
最后仔细观察终端,根据提示,发现了config.log日志,在ffbuild目录下,这个目录有好几个,别搞错了。

打开日志,滑动到最底部,看到了libsmbclient not found

继续往上滑动,我们看到了Undefined symbol .... ,大概知道了又是某些方法么定义了。
贴出关键错误:
xcrun -sdk iphoneos clang -arch arm64 -miphoneos-version-min=13.0 -fembed-bitcode -arch arm64 -miphoneos-version-min=13.0 -fembed-bitcode -I/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/openssl-arm64/output/include -I/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient/libsmbclient -L/Users/wkun/Desktop/ffmpegcodes/SGPlayer-master/build/libs/iOS/Smbclient/ -lsmbclient -ltalloc -ltdb -ltevent -lwbclient -Wl,-dynamic,-search_paths_first -o /var/folders/2m/70fjr7b53fz2zql2dmrrz5_00000gn/T//ffconf.Xxq4k0fJ/test /var/folders/2m/70fjr7b53fz2zql2dmrrz5_00000gn/T//ffconf.Xxq4k0fJ/test.o -lsmbclient
Undefined symbols for architecture arm64:
"_CFStringAppendCString", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
"_CFStringAppendPascalString", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
"_CFStringCreateMutable", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
"_CFStringCreateMutableWithExternalCharactersNoCopy", referenced from:
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_CFStringDelete", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
"_CFStringGetBytes", referenced from:
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_CFStringGetCharacters", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
"_CFStringGetLength", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_CFStringNormalize", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_CFStringSetExternalCharactersNoCopy", referenced from:
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_deflate", referenced from:
_ndr_push_compression_end in libsmbclient.a(ndr_compression.o)
"_deflateInit2_", referenced from:
_ndr_push_compression_end in libsmbclient.a(ndr_compression.o)
"_deflateReset", referenced from:
_ndr_push_compression_end in libsmbclient.a(ndr_compression.o)
"_deflateSetDictionary", referenced from:
_ndr_push_compression_end in libsmbclient.a(ndr_compression.o)
"_iconv", referenced from:
_sys_iconv in libsmbclient.a(iconv.o)
_iconvert_talloc in libsmbclient.a(reg_parse_internal.o)
(maybe you meant: _iconvert_talloc, _smb_iconv_handle_reinit , _set_iconv , _smb_iconv_open_ex , _global_iconv_handle , _lpcfg_iconv_handle , _smb_iconv_close , _smb_iconv_handle_reinit_lp , _smb_iconv_open , _get_iconv_testing_handle , _get_iconv_handle , _smb_iconv )
"_iconv_close", referenced from:
_smb_iconv_t_destructor in libsmbclient.a(iconv.o)
_set_iconv in libsmbclient.a(reg_parse_internal.o)
(maybe you meant: _smb_iconv_close)
"_iconv_open", referenced from:
_smb_iconv_open_ex in libsmbclient.a(iconv.o)
_set_iconv in libsmbclient.a(reg_parse_internal.o)
(maybe you meant: _smb_iconv_open_ex, _smb_iconv_open )
"_inflate", referenced from:
_ndr_pull_compression_start in libsmbclient.a(ndr_compression.o)
"_inflateInit2_", referenced from:
_ndr_pull_compression_start in libsmbclient.a(ndr_compression.o)
"_inflateReset", referenced from:
_ndr_pull_compression_start in libsmbclient.a(ndr_compression.o)
"_inflateSetDictionary", referenced from:
_ndr_pull_compression_start in libsmbclient.a(ndr_compression.o)
"_kCFAllocatorDefault", referenced from:
_macosxfs_encoding_pull in libsmbclient.a(charset_macosxfs.o)
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_kCFAllocatorNull", referenced from:
_macosxfs_encoding_push in libsmbclient.a(charset_macosxfs.o)
"_res_9_dn_expand", referenced from:
_ads_dns_lookup_srv in libsmbclient.a(dnsquery.o)
_ads_dns_parse_query in libsmbclient.a(dnsquery.o)
_ads_dns_parse_rr in libsmbclient.a(dnsquery.o)
_ads_dns_lookup_ns in libsmbclient.a(dnsquery.o)
"_res_9_query", referenced from:
_dns_send_req in libsmbclient.a(dnsquery.o)
"_zError", referenced from:
_ndr_pull_compression_start in libsmbclient.a(ndr_compression.o)
_ndr_push_compression_end in libsmbclient.a(ndr_compression.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ERROR: libsmbclient not found
从未定义的函数名来看,也猜不到是缺啥,最后根据CYPlayer项目进行对比,因CYPLayer中使用了smb的库,会加些系统的依赖。
由此对比,得出结论:
libsmbclient.a还需要以下4个库的依赖:
CoreFoundation.framework,libz.tbd , libiconv.tbd, libresolv.tbd
这4个库,都是iOS系统上的代码库。
FFmpeg编译时,还可以链接 framework 和 tbd动态库
指定tbd动态库的路径(xcode中在某tbd文件右键在Finder显示,找到起路径)
与指定动态库的路径一样 也是使用 -L, 链接tbd文件也是使用 -l(L的小写)
指定framework的路径也是使用 -L
链接framework需要如此: -framework CoreFoundation
这就是链接CoreFoundation.framework,不需要写拓展名。
链接tbd动态库(libz.tbd , libiconv.tbd, libresolv.tbd )以及指定其目录代码
-L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib -lz -liconv -lresolv
链接CoreFoundation.framework以及其目录代码
-L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks -framework CoreFoundation
这回再次编译,漫长的等待,成功了!!!!
编译完成后,把smb的库和头文件与ffmpeg的一并添加到项目中。
就可以测试访问smb的文件了。
有个小提示
在使用libsmbclient.a 测试时,在打开smb文件时,首先给应用申请网络权限(就是可以打开网页),不然就会打开smb文件失败。
注意,以上代码都是跟在 ./configure 命令后的参数
总结:
当你都搞定了之后,就觉得一切都很简单。
当你没搞定之前,这都是什么垃圾啊。😁
感谢以下文章:
https://www.jianshu.com/p/63bec990ee9e
https://www.jianshu.com/p/636f35f428f7
https://github.com/libobjc/SGPlayer