objc - 编译Runtime源码objc4-709

栏目: Objective-C · 发布时间: 6年前

内容简介:为了深入理解OC的Runtime机制,我们可以通过Apple开源出来的Runtime源码编译出自己的本文环境是macOS系统10.12.6,Xcode9.x打开

为了深入理解OC的Runtime机制,我们可以通过Apple开源出来的Runtime源码编译出自己的 libobjc.A.dylib ,然后自己添加target断点调试,从而深入理解objc的特性。想直接拿到可编译版本的同学,可以去我的 Github objc-709 下载。

本文环境是macOS系统10.12.6,Xcode9.x

一、下载源码

打开 苹果开源项目目录⌘+F 搜索下面的项目: objc4Libcdyldlibautolibclosurelibdispatchlibpthreadxnulaunchdlibplatform ,因为太新的版本没有我们需要的头文件,所以下载下面的版本即可:

objc4-709.1.tar.gzLibc-825.40.1.tar.gzdyld-421.2.tar.gzlibauto-77.1.tar.gzlibclosure-67.tar.gzlibdispatch-913.1.6.tar.gzlibpthread-301.1.6.tar.gzxnu-4570.1.46.tar.gzlaunchd-842.92.1.tar.gzlibplatform-125.tar.gz 。新建 objc4/ 文件夹,然后在里面新建一个 AppleSources/ 文件夹,把 objc4-709.1.tar.gz 放到 objc4/ 目录下,其余的都放到 objc4/AppleSources/ 目录下,解压所有的 .tar.gz 文件。

二、编译

1、在刚刚解压出来的 objc-709.1/ 目录下新建一个文件夹 include ,然后在objc.xcodeproj选择工程配置文件objc->TARGETS->objc->Build Settings->Search Paths->Header Search Paths中添加 $(SRCROOT)/include .

2、 # include <sys/reason.h> 处报错 sys/reason.h file not found ,解决办法为在 AppleSources/ 目录下搜索这个文件并添加到第一步新建的 include/ 目录下即可.

cd objc4/AppleSources/
find . -name "reason.h"

输出结果为: ./xnu-4570.1.46/bsd/sys/reason.h ,然后我们在 include/ 下新建 sys/ 目录,并将 reason.h 放到 include/sys/ 目录下。回到Xcode,⌘+B继续编译来解决下一个错误。

3、 # include <mach-o/dyld_priv.h> 报错,解决方法同上:

find . -name "dyld_priv.h"

输出结果为: ./dyld-421.2/include/mach-o/dyld_priv.h ,然后在 include/ 下新建 mach-o/ 目录,并将 dyld_priv.h 放到 include/mach-o/ 目录下。⌘+B继续编译

4、 # include <os/lock_private.h> 报错,同上:

find . -name "lock_private.h"

输出结果为: ./libplatform-125/include/os/lock_private.h ,然后在 include/ 下新建 os/ 目录,并将 lock_private.h 放到 include/os/ 目录下,⌘+B继续编译

5、 #include <os/base_private.h> 报错,解决办法同第四步

6、 #include <pthread/tsd_private.h> 报错,解决办法同上,在 include/ 下新建 pthread/ 目录,并将 ./libpthread-301.1.6/private/tsd_private.h 文件放到 include/pthread/ 目录下,⌘+B继续编译

7、 #include <System/machine/cpu_capabilities.h> 报错,终端下执行命令:

find . -name "cpu_capabilities.h"

这次输出结果为三个:

./xnu-4570.1.46/osfmk/arm/cpu_capabilities.h
./xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
./xnu-4570.1.46/osfmk/machine/cpu_capabilities.h

选择第三个文件(带有machine),在 include/ 下新建 System/ 目录, System/ 目录下新建 machine/ 文件夹,并将 ./xnu-4570.1.46/osfmk/machine/cpu_capabilities.h 文件放到 include/System/machine/ 目录下,⌘+B继续编译

8、 #include <os/tsd.h> 报错,终端下执行命令:

find . -name "tsd.h"

这次输出结果为两个:

./libdispatch-913.1.6/src/shims/tsd.h
./xnu-4570.1.46/libsyscall/os/tsd.h

选择第二个文件(带有os),将 ./xnu-4570.1.46/libsyscall/os/tsd.h 文件放到 include/os/ 目录下,⌘+B继续编译

9、 #include <pthread/spinlock_private.h> 报错,解决办法同第六步

10、 # include <System/pthread_machdep.h> 报错,解决办法同上,将 ./Libc-825.40.1/pthreads/pthread_machdep.h 文件放到 include/System/ 目录下

11、 # include <CrashReporterClient.h> ,解决同上,将 ./Libc-825.40.1/include/CrashReporterClient.h 文件放到 include/ 目录下

12、 #include_next <CrashReporterClient.h> ,通过源码及注释可知 #ifdef LIBC_NO_LIBCRASHREPORTERCLIENT 为TRUE时,就不会编译报错了。这里改下工程配置,在 Build Settings->Preprocessor Macros 中Debug和Release都添加 LIBC_NO_LIBCRASHREPORTERCLIENT ,⌘+B继续编译

13、 #include <pthread/workqueue_private.h> ,解决办法同第6步

14、 #include <pthread/qos_private.h> ,终端下执行命令:

find . -name "qos_private.h"

这次输出结果为两个:

./libpthread-301.1.6/private/qos_private.h
./libpthread-301.1.6/sys/qos_private.h

选择第一个文件,将 ./libpthread-301.1.6/private/qos_private.h 文件放到 include/pthread/ 目录下;同时选择第二个文件,将 ./libpthread-301.1.6/sys/qos_private.h 文件放到 include/sys/ 目录下,⌘+B继续编译

15、 #include <objc-shared-cache.h> 报错,解决办法同第11

16、 #include <_simple.h> ,终端下执行命令:

find . -name "_simple.h"

这次输出结果为两个:

./Libc-825.40.1/gen/_simple.h
./libplatform-125/include/_simple.h

选择第二个文件,将 ./libplatform-125/include/_simple.h 文件放到 include/ 目录下,⌘+B继续编译

17、 objc-os.h 里第778行报 Unknown type name 'pthread_priority_t' 错误,780行报 Use of undeclared identifier 'pthread_priority_t' 错误,782行报 Use of undeclared identifier '_PTHREAD_PRIORITY_FLAGS_MASK' 错误,在终端下执行命令:

grep -re 'typedef.*pthread_priority_t' .
grep -re 'def.*_PTHREAD_PRIORITY_FLAGS_MASK' .

对比结果发现 ./libpthread-301.1.6/private/qos_private.h 出现了两次,因为之前我们已经将该文件放到了 include/pthread/ 目录下,所以直接在 objc-os.h 前面引入它即可:

#include <pthread/qos_private.h>

18、 #include <Block_private.h> 报错,终端下执行命令:

find . -name "Block_private.h"

这次输出结果为两个:

./libclosure-67/Block_private.h
./libdispatch-913.1.6/src/BlocksRuntime/Block_private.h

选择第一个文件,将 ./libclosure-67/Block_private.h 文件放到 include/ 目录下,⌘+B继续编译

19、 ld: can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/AppleInternal/OrderFiles/libobjc.order
因为 libobjc.order 已经存在 $SRCROOT 下,即 objc-709.1/ 目录下,所以我们改下工程配置: Build Settings->Linking->Order File ,把Debug和Release下的 $(SDKROOT)/AppleInternal/OrderFiles/libobjc.order 改为 libobjc.order

20、 ld: library not found for -lCrashReporterClient ,继续改工程配置: Build Settings->Linking->Other Linker Flags 里Debug和Release下删掉 -lCrashReporterClient 。此时按⌘+B应该会编译成功了,编译工作基本完成。

三、调试

编译libobjc.A.dylib成功后,我们可以尝试自己调试,新建一个Target,选择macOS下的Command Line Tool,命名为 debug-objc
objc - 编译Runtime源码objc4-709

然后选中TARGETS下的 debug-objc ,选择 Build Phases->Target Dependencies ,把 objc 的Target加进来。接着在 debug-objc/main.m 中添加你想调试的代码即可

objc - 编译Runtime源码objc4-709

四、结语

接下来就尽情的调试学习 objc 的源码吧,如果你想直接使用编译好的版本,点击 Github objc-709 下载即可。


以上所述就是小编给大家介绍的《objc - 编译Runtime源码objc4-709》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

构建之法(第二版)

构建之法(第二版)

邹欣 / 人民邮电出版社 / 2015-7 / 59

软件工程牵涉的范围很广, 同时也是一般院校的同学反映比较空洞乏味的课程。 但是软件工程的技术对于投身IT 产业的学生来说是非常重要的。作者邹欣有长达20年的一线软件开发经验,他利用业余时间在数所高校进行了长达6年的软件工程教学实践,总结出了在16周的时间内让同学们通过 “做中学 (Learning By Doing)” 掌握实用的软件工程技术的教学计划,并得到高校师生的积极反馈。在此基础上,作者对......一起来看看 《构建之法(第二版)》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具