iOS中的符号冲突(二)- 理解进阶
- iOS中的符号抵触(一)- 根底原理
符号其实便是文件里界说的函数或者办法在 Mach-o中的名称
实际上运转app的时分,履行的是机器码
机器码经过反汇编之后,会生成咱们平时见到的汇编代码
app去掉符号之后,能不能运转呢?
继续弥补一些根底知识
xcode 能够理解为一个大号的脚本
-
xcode编译过程中,需求处理编译文件里的头文件
-
比如编译framework的时分,首先在编译途径里创建一个编译产物途径
-
生成一个 产物途径 跟 当前真正的符号头文件匹配的 虚拟文件系统 VFS
-
复制头文件到编译产物途径/headers目录
-
-
调起clang (包含汇编器 链接器) 开始编译每一个.m .cpp文件,最终生成可履行文件
-
sign 进行签名
-
strip 进行符号处理
xcconfig 操控build setting, build setting 操控以上整个产物生成流程
如何操控呢
要履行clang的命令,包含脚本的命令,势必要有一个shell环境
clang需求参数才能对.m文件编译 参数传递给clang,经过clang传递给链接器ld
build setting 装备选项怎样在shell环境里生效
shell – 环境变量,shell把build setting每一个装备选项变成 环境变量
xcconfig 每一个装备选项都是 key = value的形式,key会被xcode导成要履行的shell的环境变量 clang用环境变量拼接成需求的参数
咱们常常会在xcode 创建一个 run script,能直接拜访build setting变量,原因便是xcode会把build setting装备变量装备成 shell环境变量
符号类型弥补
-
上一篇博文中提到了 大局符号、本地符号
大局符号的效果域为整个进程,本地符号(static)只效果于声明的文件
-
还有导入、导出符号
#import <Foundation/Foundation.h> 便是把Foundation动态库里的符号导入到当前工程
Foundation动态库里露出的符号就称为 导出符号
NSLog 在Foundation动态库里,归于大局符号,相对于Foundation,归于导出符号,相对于app归于导入符号
app运转起来之后,除了需求动态库的大局符号,其他符号一概不需求
动态库也是,除了大局符号,其他符号不需求
大局符号有导入 导出效果,需求供给给他人
app里的大局符号能被脱除
- 由于符号的一个效果便是作为标记汇编代码,假如汇编代码能够直接找到,就不需求符号了,说白了app里的大局符号便是一个地址,直接找地址就OK了,不需求再标记符号,然后依据符号再找了
- 符号其实大概率是给程序员做调试的
弱界说/弱引证符号
-
Weak Reference Symbol
表示此未界说符号是弱引证,假如dyld(动态链接器)找不到该符号的界说,则将其设置为0, 静态链接器 找不到 编译就会报错
-
void weak_import_function(void) attribute ((weak_import));
弱引证符号 xcconfig 设置
OTHER_LDFLAGS = $(inherited) -Xlinker -U -Xlinker _weak_import_function
weak_import_function没有完成,直接运用,编译不会报错
经过xccondig装备 经过编译器告诉链接器忽略 符号 _weak_import_function是否界说,由动态链接器担任 这样 编译正常经过
在运用函数时,经过判别进口地址非nil 再履行
尽管编译器会提示:
Address of function ‘weak_import_function’ will always evaluate to ‘true’
编译器提示 函数进口判别永远不会为空, 这是由于还没有经过动态链接器dyld,还未处理若引证符号 设置为0也便是nil,所以编译器会告警
运转阶段,动态链接器dyld找不到符号,将符号设置为0,也便是置为nil, 并不会履行,不用担心溃散问题
-
动态库本身是个大号的符号表,假如想让动态库里的一切符号全为弱引证符号,如何操作
-
针对动态库有一个专门的参数,-weak_framework 指定为弱引证的动态库,会把动态库里的一切的符号都标记为弱引证
-
spec -> cocoapods 怎样操控framework编译
cocoapods其实便是经过xccondig 来操控的,就能够传递 恣意参数 像 -weak_framework
-
-
扩展知识
-
动态库 运转的时分,经过途径的方法链接,动态库或许被莫名删掉了,运转时报错
-
经过 -weak_framework 动态链接器dyld找不到就置nil,不溃散
-
手动链接framework
引进framework头文件
编译犯错 – 未界说的符号 _global_home_fun
xcconfig 该用链接参数 weak_framework
global_home_fun 加上非nil判别
再次编译success
运转,希望成功,但是仍然过错
过错提示的是 一级命名空间内 符号找不到
尽管手动链接 framework,-weak_framework 并未能按照ld手册里描述的那样,把链接的framework里一切符号均标记为弱引证符号,但是能够帮助咱们理解 符号的查找过程
能够自己做个测验,framework均完成同名大局函数,app中调用函数,履行的是app中的函数完成
假如framework中只声明,未完成的话,app中调用函数 履行的仍然是app中的函数完成
所以,app中的同名符号 先于 framework被找到,而假如app与framework中均未界说,则该符号不存在比较是否相同,也就没有了两级命名空间,在任何一个framework中都不存在,所以便是flat namespace,报symbol not found过错
假如在你的app中用到一个framework中未界说的符号,最直接的方法,便是在你的app中界说一个同名的符号
-
-dead_strip_dylibs 告诉链接器,假如dylibs没有供给符号,就停止load此dylib,慎用
-
-
-
Weak definition Symbol
弱界说符号,假如静态链接器或dyld为此符号找到另一个(非弱)界说,则弱界说将被忽略
假如不确定自己app或framework中的符号在一些其他framework中已界说,最好的方法便是界说为 弱界说符号,没有什么丢失
-
我正在参加技能社区创作者签约方案招募活动,点击链接报名投稿