库
库(Library)就是一段编译好的二进制代码,加上头文件就可以供别人使用
库文件格式
.a:常见的静态库.dylib:传统上说的动态库.framework:既有动态库,又有静态库.xcframework:是苹果2018年推出来的,可以将不同架构的库整合到一起。好处就是模拟器,真机可以通用,上架AppStore,不需要将xcframework中的真机架构分离,.framework还需要用脚本分离
库的使用场景
- 某些
代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只`暴露出头文件。 - 对于某些
不会进行大的改动的代码,我们想减少编译的时间,就可以把它打包成库,因为库是已经编译好的二进制了,编译的时候只需要Link一下,不会浪费编译时间。
静态库与动态库
静态库
静态库即静态链接库:可以简单的看成一组目标文件的集合。即很多目标文件经过压缩打包后形成的文件。Windows下的 .lib,Linux 和 Mac 下的 .a。Mac独有的.framework。
- 缺点:
浪费内存和磁盘空间,模块更新困难
动态库
与静态库相反,动态库在编译时并不会被拷⻉到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。格有:.framework、.dylib、.tdb。
- 缺点:
会导致一些
性能损失。但是可以优化,比如延迟绑定(Lazy Binding)技术
静态库生成
生成.o文件
编译过程是首先就是要生成目标文件(也就是.o文件),之后通过链接器生成可执行文件 所以将我们最上面的.m文件先生成.o文件,用到我们经常使用的clang命令, clang就是C、C++和OC的编译器
clang -x objective-c \
-target x86_64-apple-macos11.3 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk \
-I./AFNetworking \
-c test.m -o test.o
命令解释
- 1.
-x:制定语言,/:转译字符,输入后告诉终端敲回车是换行,不是执行 - 2.
制定平台 - 3.
编译成arc环境 - 4.
指定使用的SDK路径 - 5.
I 在指定目录寻找头文件AFN如果没有引用到外部库就不加 - 6.
将.m编译成.o
回车就生成了.o文件
生成静态库
将生成的.o文件通过链接器生成静态库
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk \
-L./AFNetworking \
-lAFNetworking \
test.o -o test
- 1.这里不需要制定语言,
直接选择架构 - 2.选择
arc环境 - 3.由于项目中
有NSLog,其导出符号,要知道其来源自Foundation,让他去我们指定的Xcode中寻找 - 4.指定目录寻找头文件(
链接的过程就是把我们重定位符号表中的符号进行重定位,这里就需要知道符号的真实位置,AFN的符号表放在了libAFNetworking.a文件里了,它需要和我们生成的test.o文件的符号表进行融合,最后生成一张新的符号表) - 5.指定
连接的库文件名称 - 6.将
.o文件输出为test文件
有个细节注意架构问题,如果引用不同架构,导出的时候会报错 x86架构
ar生成.a静态库
1.在OCStaticLib文件夹中准备OCTest.h和OCTest.m两个简单的类文件
2.将OCTest.m编译成.o目标文件
clang -x objective-c \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-c OCTest.m \
-o OCTest.o
3.将OCTest.o文件生成.a静态库
//生成 .a 文件
ar -rc libOCTest.a OCTest.o
// 查看包含的目标文件
ar -t +Path
-
ar参数说明-r:向.a中添加或替换文件(无则添加, 有则替换)-c:不输出任何信息-t:列出包含的目标文件
静态库合并
1.静态库是.o文件的合集, 静态库合并就是将静态库的.o合并, 可以实现的工具
ar, 静态库的查看、拆分、合并libtool,xcode提供的静态库操作工具
libtool \
-static \
-o \
libMerge.a \
libAFNetworking.a \
libSDWebImage.a
-
参数说明
libMerge.a是合并后生成静态库的名称libAFNetworking.a和libSDWebImage.a是将要被合并的两个静态库
-
利用
ar来验证下静态库文件是否包含两个静态库的.o文件
ar -t /Users/shenyj/Documents/CodeForTest/staticLibMerge/staticLib/libMerge.a
制作脚本
LANGUAGE=objective-c
TAREGT=x86_64-apple-macos11.3
SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk
FILE_NAME=test
STATICLIBRARY=TestExample
HEAD_PATH=./StaticLibrary
LIBRARY_PATH=./StaticLibrary
echo "-------------编译test.m to test.o------------------"
clang -x $LANGUAGE \
-target $TAREGT \
-fobjc-arc \
-isysroot $SYSROOT \
-I${HEAD_PATH} \
-c ${FILE_NAME}.m -o ${FILE_NAME}.o
echo "-------------进入到StaticLibrary目录------------------"
pushd ${HEAD_PATH}
echo "-------------编译TestExample.m to TestExample.o------------------"
clang -x $LANGUAGE \
-target $TAREGT \
-fobjc-arc \
-isysroot $SYSROOT \
-c ${STATICLIBRARY}.m -o ${STATICLIBRARY}.o
echo "-------------退出StaticLibrary目录------------------"
popd
echo "-------------test.o链接libTestExample.a to test EXEC------------------"
clang -target $TAREGT \
-fobjc-arc \
-isysroot $SYSROOT \
-L${LIBRARY_PATH} \
-l${STATICLIBRARY} \
$FILE_NAME.o -o $FILE_NAME
权限相关
chmod +x ./build.sh
./build.sh
lldb
file test
r
静态库优化
1.通过xcconfig来取代build settings设置
// Xlinker 作用告诉 clang 参数传递给 lldb 使用
// -Xlinker -all_load:不dead strip,加载全部代码
// -Xlinker -ObjC:加载全部OC相关代码,包括分类
// -force_load: 要加载那个静态库的全部代码
LGSTATIC_FRAMEWORK_PATH=${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/LGStaticFramework.framework/LGStaticFramework
OTHER_LDFLAGS=-Xlinker -force_load ${LGSTATIC_FRAMEWORK_PATH}
-
其中
Xlinker的作用OTHER_LDFLAGS通过clang给ld传递参数- 并不是给
clang的参数,clang没有这些参数(-ObjC…), 通过Xlinker告诉clang传递给ld
重点 LTO Link-Time Optimization, dead strip之后执行的 优化代码体积。暂不陈述,以后会补充
总结
生成静态库的三要素:
-I:-I<directory>在指定目录寻找头文件, 等同于Build Setting设置header search path-L:-L<dir>指定库文件路径(.a.dylib库文件, 等同于Build Setting设置library search path-l:-l<library_name>指定链接的库文件名称(.a.dylib库文件), 等同于Build Setting设置other link flags -lAFNetworking
补充
- clang命令参数:
-x: 指定编译文件语言类型-
-g: 生成调试信息 -
-c: 生成目标文件,只运行preprocess,compile,assemble,不链接 -
-o: 输出文件 -
-isysroot: 使用的SDK路径 -
-I: 在指定目录寻找头文件 header search path -
-L: 指定库文件路径(.a.dylib库文件) library search path -
-l: 指定链接的库文件名称(.a.dylib库文件)other link flags -
-F: 在指定目录寻找framework framework search path -
-framework <framework_name>指定链接的framework名称 other link flags -framework AFNetworking