以 OpenCV 为例,介绍一些常见的二进制库工具。
可以使用 file
命令查看支持的架构,也可以看到是静态库还是动态库。
当然 file
命令还可以用来查看其他文件的一些基本参数,比如查看一个音频文件的参数 👇🏻
可以看到这个 wav
音频是一个小端存储、采样数据格式为 PCM、16 位深、采样率 48000。
查看一个二进制文件的符号可以使用 nm
命令。
一个比较常见的操作是配合 grep
来查找过滤某些符号 👇🏻
nm opencv2.framework/opencv2 | grep CodedOutputStream
nm
的输出里,除了能看到具体符号外,符号的左侧还有个字母,比如 U
、S
等,代表该符号的类型。
符号类型 | 解释 |
---|---|
A | Absolute symbol, global |
a | Absolute symbol, local |
B | Uninitialized data (bss), global |
b | Uninitialized data (bss), local |
D | Initialized data (bbs), global |
d | Initialized data (bbs), local |
F | File name |
l | Line number entry (see the –a option) |
N | No defined type, global. This is an unspecified type, compared to the undefined type U. |
U | No defined type, local. This is an unspecified type, compared to the undefined type U. |
S | Section symbol, global |
s | Section symbol, local |
T | Text symbol, global |
t | Text symbol, local (static) |
U | Undefined symbol |
类型较多,不过其实一般只需要记住这两个基本原则:
global
符号,小写字母代表 local
符号U
这种符号是 undefined
,很多时候链接时找不到符号有可能是这里的问题:虽然有符号,但是符号是 Undefined
因为经常同一个库支持多个架构,我们还可以限制只打印某个架构的符号 👇🏻
nm --arch arm64 opencv2.framework/opencv2
DWARF 的全称是 debugging with attributed record formats,是一种源码调试信息的格式,iOS 经常用到,之前已经单独写了文章,想起可以参考 iOS 符号之 DWARF 和 dSYM。
主要是用 dsymutil
导出调试符号文件,然后用 dwarfdump
查看。
一个库可能支持多个架构,比如 arm64
、x86_64
等等,我们可以使用 lipo
做一些拆分合并操作。
将某个多架构库的其中某个架构的内容抽成独立的库。
lipo -extract arch_type file
🌰 👇🏻:
lipo -remove x86_64 opencv2.framework/opencv2 -output openCV2_arm64
注意,通过上面的方式得到的库还是多架构库,只是只包含一种架构。
如果想获得一个单架构库可以通过下面的方式 👇🏻
lipo -thin arch_type <input> -output output
🌰 👇🏻:
lipo -thin arm64 opencv2.framework/opencv2 -output openCV2_arm64_thin
lipo -remove arch_type <input> -output <output>
🌰 👇🏻:
lipo -remove x86_64 opencv2.framework/opencv2 -output openCV2_without_x86_64
lipo -create <input1> <input2> ... -output opencv2.framework/opencv2
🌰 👇🏻:
lipo -create openCV2_arm64 openCV2_x86_64 -output opencv2.framework/opencv2
举个例子,如果你的 Test.framework
里用到了另一个 Test.a
,一般来讲我们可以将 Test.a
合并到 Test.framework
里,这样使用方只需要理解和引用 Test.framework
就可以了,不需要关心 Test.a
的存在。
我们可以通过下面这个方式合并:
// 创建静态库
libtool -static -o output input1 input2 input3 ...
// 创建动态库
libtool -dynamic -o output input1 input2 input3 ...
libtool -static -o Test.framework/wxaudio Test.a Test.framework/wxaudio
此外,一些常见的参数如下:
参数 | 作用 |
---|---|
-v | 详细模式,会把执行细节打印出来,方便查问题 |
-arch_only | 只合并某个架构,其他架构会被忽略 |