xcode 的app工程与ffmpeg 4.4版本的静态库联调,ffmpeg内下的断点无法暂停。

先阐述一下我的业务场景,我有一个iOS的app sdk项目,下面简称 A ,以及运行 A 的 app 项目,简称 A demo 。

引用关系为 A demo 引用了 A ,而 A 引用了 ffmpeg 的静态库(.a文件)。此时业务出现了 bug ,测试后得知,bug 来自于ffmpeg。现在无法定位ffmpeg的问题出在哪里,需要在程序运行时,断点停在ffmpeg的源码中。而直接拉入ffmpeg是无法下断点的,断点无效(就是代码行数上那个虚线边框中心透明的图标)。经过各种方式研究,现在做出总结。

代码是公司的,github就不放出来了
其实对于静态库的源码断点调试可以有三种方式:

一、如果工程中有可执行文件,可以直接调试源码,例如ffmpeg的ffmpeg_g可执行文件,缺点是与项目脱离,无法从iOS项目中直接进入(也可能是我没找到方法,反正我是没成功)。无法暂停项目的调试真的很难排查问题在哪。本文不讨论该方法

二、make生成有符号表的静态库文件,项目A引用该文件,并将静态库源码直接拉入工程。通过xcode断点调试。该方法可行,但是不知道ffmpeg为什么不可以,通过nm命令查看符号表,也都正常。但就是不行。然后我选择了第三种方式

三、直接源码调试,就是新建xcode 的静态库工程,然后生成静态库后由A引用,并在A工程中拉入ffmpeg的源码,利用xcode设置断点。实测可以,缺点就是编译ffmpeg时候会有很多奇怪的问题,需要一一解决。我最后采用的就是这种方式。

针对第三种方法,这种其实在逻辑上是最简单的,首先需要新建一个xcode工程,因为是我的是iOS项目,所以我选的是 static library。把ffmpeg的文件夹拉入工程,然后清空compile sources 后面会告诉你哪些需要拖入这个地方,这个工程编译成功后就是.a静态库。然后在build configuration中设置为debug 。别忘了在header search中配置好路径,不然会找不到文件,这里很简单,我就不赘述了,不会的可以去百度。

因为ffmpeg是有多个静态库的,建议一个target对应一个静态库,方便管理和编译,后面往项目A里也只需要拉动ffmpeg的哪个.xcodeproj 文件就行了。也很方便。最后弄好的工程界面应该是这样

那么ffmpeg那么多文件,哪些文件是需要编译的,这才是本文的重点。通常从ffmpeg官方库中下载的源代码,会有一个可执行文件configure,该文件的主要作用是生成一个可以用来make编译ffmpeg的config.h文件,这个config才是最重要的,它里面写了你所需要的配置需要编译哪些文件。他长这样

其实就是一堆宏定义。那么光看他怎么知道哪些文件是需要的还是不够的,你还需要看对应静态库源码文件夹内的makefile文件,因为ffmpeg是通过make编译,而make就是通过config和makefile文件结合来排查那些文件编译的,你需要把make编了哪些文件找到。举个例子,比如我现在想编译libavutil.a这个库,那么你就需要打开libavutil的目录下的makefile文件。见下图

这就很明显了,headers 后面的所有.h文件就是编译静态库后那个Headers文件夹里所有头文件,那么就要把对应的文件拖入这里

这样就会在生成静态库时生成header文件夹了

对于.c文件的编译要在ffmpeg的makefile中找 objs 这个变量里有哪些文件,这里每个.o就是对应.c文件编译过来的,可以假装.o就是.c。

那你会注意到,后面还有很多这样的代码,

这里就是和config联动的地方,我红色框出来的内容,实际上就是config的宏定义,在config中对应的是0或者1,如果是1,那么该行后面的出现的文件名就是要编译的,如果是0,那么就是不需要的。将上面所有需要的.c文件都拖入到这里,注意,别拖错target了

好有就是,根据不同的平台要拖入对应的平台文件,我是iOS项目,也就是arm64,要把汇编文件拖进去,也就是.s文件,其他的该目录下的.c一般不需要。

此时就可以 command + b 编译了。但是会有很多报错,我说一下我遇见的

如果下图报错,那么说明你把不该编译的编译进来了,例如这个tx_template.c,去掉就可以了,注意,不是删除文件啊,文件还在,只是不编译了。

如果类似出现No matching function for call to 'av_pix_fmt_desc_get' 就是缺少头文件,查一下av_pix_fmt_desc_get 函数在哪个.h文件里,一般都是internal.h 在上面添加#include""就行了,如果已经添加了还是报错,那就说明没编译,要把有av_pix_fmt_desc_get 对应的.c文件放入complie sources里。

对于编译其他库时候,也会需要用到libavutil的internal.h,加入把这个写进去就行了#include "libavutil/internal.h",注意head search目录,得让他找得到

对于libavformat,如果你引用了openssl 或者srt,那么你还得添加依赖到link binary中并在library search配置好目录就行了。

对于avutil 源码编译时,ffmpeg有自己的time.h 和time.c文件,xcode会有可能出现于系统库里的time.c和time.h冲突,导致报错,例如 struct tm 、clock()、nanosleep无法找到,但是头文件#include <time.h>明明添加了,这就说明冲突了,给ffmpeg 的time.c和time.h改名就行了。

如果编译成功了,那么恭喜你,完成了一大半。现在你可以在A中引入生成的静态库了,然后编译A,如果报错 Undefined symbol: _av_gettime 说明 av_gettime这函数、变量或者宏定义没找到,你在ffmpeg中找到这个函数所在的.c文件,然后拖到complie sources里,重新编译就行了

上诉问题解决了,大概率就能用了,这时A工程的workspace中拖入ffmpeg的.xcodeproj文件,然后在对应的位置设置断点就可以直接使用了。

从iOS Ademo 启动,断点停在ffmpeg源码如下图

相关推荐
青花瓷6 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
岁月小龙7 小时前
如何让ffmpeg运行时从当前目录加载库,而不是从/lib64
ffmpeg·origin·ffprobe·rpath
2401_865854888 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
HackerTom20 小时前
iOS用rime且导入自制输入方案
ios·iphone·rime
良技漫谈20 小时前
Rust移动开发:Rust在iOS端集成使用介绍
后端·程序人生·ios·rust·objective-c·swift
2401_8524035520 小时前
高效管理iPhone存储:苹果手机怎么删除相似照片
ios·智能手机·iphone
星际码仔1 天前
【动画图解】是怎样的方法,能被称作是 Flutter Widget 系统的核心?
android·flutter·ios
emperinter1 天前
WordCloudStudio:AI生成模版为您的文字云创意赋能 !
图像处理·人工智能·macos·ios·信息可视化·iphone
关键帧Keyframe1 天前
音视频面试题集锦第 8 期
ios·音视频开发·客户端
pb82 天前
引入最新fluwx2.5.4的时候报错
flutter·ios