【后端教程】揭秘NSRuntime源码编译

RunTime是什么?

C语言,函数的调用在编译的时候会决定调用哪个函数。编译完成之后直接顺序执行,无任何二义性。而OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

我们如何找到RunTime源码?

Runtime源码下载链接:https://opensource.apple.com/release/macos-10141.html

打开链接,搜索objc 找到objc4最新版本下载即可。

本文编译环境

1、 Xcode版本:11.2.1

2、 MacOS版本:10.14.6

3、 Runtime版本:objc4-750.1

对于不同的Runtime版本及Xcode版本可能出现的错误也不一样,这篇文章主要是我在编译过程中遇到的错误信息以及解决方案,如果大家没有遇到对应的错误信息,直接跳过即可。

编译过程

打开objc.xcodeproj,编译运行,

1、编译报错:

image

解决方案:按图中步骤将Architectures选择Stand Architectures,点击objc target,也如下图修改。

image

2、编译报错,会缺少很多的文件

第一步:打开链接https://opensource.apple.com/release/macos-10141.html 下载:Libc、dyld、libauto、libclosure、libdispatch、xnu、libpthread、launchd、libplatform,全部下载下来解压到统一个目录下。

第二步:新建文件夹Common,之后我们会把所有的报错文件都放到该文件夹下。

第三步:Header search path,debug及release下添加$(SRCROOT)/Common,如下图。

image

第四步:逐步编译添加缺少的文件。

报错1:‘reason.h’ file not found

解决方案:打开终端,cd到第一步中统一的目录下,执行命令:find . -name ‘reason.h’ ,

终端打印./xnu-4570.71.2/bsd/sys/reason.h

在Common目录下新建sys文件夹,到文件加下该文件夹下找到reason.h 添加到项目sys文件夹下,继续编译。

报错2:‘dyld_priv.h’ file not found,所在路径:./dyld-655.1.1/include/mach-o/dyld_priv.h,

添加后会在dyld_priv.h文件中报错Expected ‘,’ 注释掉即可

*通上述步骤可找到文件添加到工程,为节省大家时间,相同的操作会列出缺少文件及对应找的目录

报错3:‘lock_private.h’ file not found

路径:./libplatform177.200.16/private/os/lock_private.h

报错4:‘base_private.h’ file not found

路径:./libplatform177.200.16/private/os/base_private.h

报错5:‘tsd_private.h’ file not found

路径:./libpthread-330.250.2/private/tsd_private.h

报错6:‘cpu_capabilities.h’ file not found

如果执行find . -name 'cpu_capabilities.h’会有三个文件,我们用./xnu-4570.71.2/osfmk/machine/cpu_capabilities.h 目录下文件

报错7:‘tsd.h’ file not found

会有两个文件,我们用:./xnu-4570.71.2/libsyscall/os/tsd.h

报错8:‘spinlock_private.h’ file not found

路径./libpthread-330.250.2/private/spinlock_private.h

报错9:‘pthread_machdep.h’ file not found

采用上述方案找不到该文件,我们需要采取新的方案,即在google搜索pthread_machdep打开第一条,自己在Common/System下新建文件,将内容拷贝进去。

拷贝后会报错:Typedef redefinition with different types (‘int’ vs ‘volatile OSSpinLock’ (aka ‘volatile int’)) 解决方案 将该文件中报错的地方注释掉

*注意如果注释不全这会报错-如果没有下图报错跳过次步骤

image

解决方案:一定将pthread_machdep.h文件中inline static int 这行代码注释掉

错误10:‘CrashReporterClient.h’ file not found

同报错9一样的方式解决,

错误11:‘Block_private.h’ file not found

路径./libclosure-73/Block_private.h对应目录./libdispatch-1008.250.7/src/BlocksRuntime/Block_private.h

错误12:‘objc-shared-cache.h’ file not found

路径:./dyld-655.1.1/include/objc-shared-cache.h

错误13:’_simple.h’ file not found

路径./libplatform-177.200.16/private/_simple.h

错误14:‘dyld_priv.h’ file not found

路径./dyld-655.1.1/include/mach-o/dyld_priv.h

错误15:‘isa.h’ file not found

路径./objc4-750.1/runtime/isa.h

3、编译报错:

Use of undeclared identifier ‘CRGetCrashLogMessage’

解决方法:target -> Build Settings -> Preprocessor Macros 添加LIBC_NO_LIBCRASHREPORTERCLIENT,如下图。

image

4、编译报错:

Use of undeclared identifier ‘DYLD_MACOSX_VERSION_10_13’

解决方案:在dyld_priv.h中添加下边代码:

#define DYLD_MACOSX_VERSION_10_11 0x000A0B00

如下图:

image

5、继续编译报错:

can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/AppleInternal/OrderFiles/libobjc.order

解决方法:如下图target -> objc -> Build Settings -> Order File

加入:$(SRCROOT)/libobjc.order,如下图:

image

6、继续编译报错:

library not found for -lCrashReporterClient

解决方法:删除lCrashReporterClient,如下图:

image

7、继续编译报错:

Undefined symbol: _objc_opt_class:

解决方法:

image

8、继续编译报错:

image

•解决方法:选择 target -> objc -> Build Phases -> Run Script(markgc)

•把脚本文本 macosx.internal 改成 macosx

9、继续编译报错:

error: no such public header file: '/tmp/objc.dst/usr/include/objc/ObjectiveC.apinotes'

解决方法:选择 target -> objc -> Build Settings

•Text-Based InstallAPI Verification Model 中添加搜索路径 Errors Only

将Supports Text-Based Install API 设为NO

image

编译通过

新建Target:runtimeTest 运行runtimeTest,runtimeTest下main.m文件里可以断点查看runtime源码。

服务推荐

发布了0 篇原创文章 · 获赞 0 · 访问量 472

猜你喜欢

转载自blog.csdn.net/weixin_47143210/article/details/105728879