Runtime,是一套底层的 C 语言 API,是 iOS 系统的核心之一。开发者在编码过程中,可以给任意一个对象发送消息,在编译阶段只是确定了要向接收者发送这条消息,而接受者将要如何响应和处理这条消息,那就要看运行时来决定了。
C语言中,在编译期,函数的调用就会决定调用哪个函数。
而OC的函数,属于动态调用过程,在编译期并不能决定真正调用哪个函数,只有在真正运行时才会根据函数的名称找到对应的函数来调用。
Objective-C 是一个动态语言,这意味着它不仅需要一个编译器,也需要一个运行时系统来动态得创建类和对象、进行消息传递和转发。
调试环境
- Xcode版本: 10.1
- Runtime源码版本: objc4-750.1
代码地址
版本750.1官方源码地址: objc4-750.1.tar.gz
官方历史源码地址列表: runtime历史源码版本列表
让Runtime源码可以编辑步骤还是比较多这里放置一份我已经编译通过的代码 点这里
开始编译源代码
下载完代码的目录如图
最终结果就是编译Products目录下的libobjc.A.dylib。开始编译按照提示依次解决直到成功编译。
1. i386架构废弃
- 错误提示信息
The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture. (in target 'objc-trampolines')
The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture. (in target 'objc')
提示的是在target 'objc-trampolines' 和 'objc'中i386已经废弃了。
- 解决方案
分别从tatget中移除i386架构,进入TARGETS->objc->Build Settings->Architectures 将"Debug"修改成Standard Architectures
2. 缺少文件
缺少的文件点击 这里下载。
- 错误提示信息
会出现以下缺失文件的提示下面罗列出来
'sys/reason.h' file not found
'mach-o/dyld_priv.h' file not found
'os/lock_private.h' file not found
'os/base_private.h' file not found
'pthread/tsd_private.h' file not found
'System/machine/cpu_capabilities.h' file not found
'os/tsd.h' file not found
'pthread/spinlock_private.h' file not found
'System/pthread_machdep.h' file not found
'Block_private.h' file not found
'objc-shared-cache.h' file not found
'_simple.h' file not found
- 解决方案
在工程目录下创建一个新的文件夹名字可以随便起我命名为Common将刚才下载的文件都放在里面,
接下来把文件添加到Header Search Paths中,进入TARGETS->objc->Build Settings 直接搜索Header Search Paths,把$(SRCROOT)/Common添加进去。
下面根据信息的提示在Common目录下新建文件夹sys,将刚才下载的reason.h文件拖动到sys文件夹里这样我们就解决了sys/reason.h' file not found这个错误,其他的提示都是类似解决方法。
3. pthread_machdep.h文件的错误
- 提示信息
Static declaration of '_pthread_has_direct_tsd' follows non-static declaration
Static declaration of '_pthread_getspecific_direct' follows non-static declaration
Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int'))
-
解决方案
注释掉pthread_machdep.h中错误提示代码,从提示的位置注释到最后。
4. objc-runtime-new.mm文件的错误
- 错误提示信息
Use of undeclared identifier 'DYLD_MACOSX_VERSION_10_11'
Use of undeclared identifier 'DYLD_MACOSX_VERSION_10_14'
- 解决方案
在我们刚刚添加的Common文件夹中的dyld_priv.h头部添加相关的宏定义。
#define DYLD_MACOSX_VERSION_10_11 0x000A0B00
#define DYLD_MACOSX_VERSION_10_12 0x000A0C00
#define DYLD_MACOSX_VERSION_10_13 0x000A0D00
#define DYLD_MACOSX_VERSION_10_14 0x000A0E00
5. 缺少CrashReporterClient.h
CrashReporterClient.h文件仅仅放在Common目录下还不行还要做一些其他处理。
- 错误提示信息
Use of undeclared identifier 'CRGetCrashLogMessage'
Use of undeclared identifier 'CRSetCrashLogMessage'
- 解决方案
进入TARGETS->objc->Build Settings 直接搜索preprocessor,在Preprocessor Macros中添加 LIBC_NO_LIBCRASHREPORTERCLIENT。
6. can't open order file
- 错误提示信息
ld: can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/AppleInternal/OrderFiles/libobjc.order
clang: error: linker command failed with exit code 1 (use -v to see invocation)
- 解决方案
进入TARGETS->objc->Build Settings->Linking->Order File 修改为$(SRCROOT)/libobjc.order。
7. not found for -lCrashReporterClient
- 错误提示信息
ld: library not found for -lCrashReporterClient
clang: error: linker command failed with exit code 1 (use -v to see invocation)
- 解决方案
进入TARGETS->objc->Build Settings->Linking->Other Linker Flags中删除lCrashReporterClient,DEBUG和RELEASE都删除。
8. macosx.internal不能被定位到
- 错误提示信息
SDK "macosx.internal" cannot be located.
unable to find utility "clang++", not a developer tool or in PATH
- 解决方案
进入TARGETS->objc->Build Phases->Run Script,将脚本里面的macosx.internal->macosx。
9. public header
- 错误提示信息
no such public header file: '/tmp/objc.dst/usr/include/objc/ObjectiveC.apinotes'
- 解决方案
第一步: 进入TARGETS->objc->Build Settinngs->Text-Based API->Other Text-Based InstallAPI Flags,将里面的内容设置为空。
第二步: 将Text-Based InstallAPI Verification Mode改为Errors Only,如图
编译成功
到此为止这份源代码就可以通过编译了,现在看一下工程目录,可以看到Products下面的库变成了黑色。
添加新的TARGETS进行调试
PS: 后续会有一系列关于runtime的总结,如有理解不妥,欢迎交流