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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Spring Cloud微服务实战

Spring Cloud微服务实战

翟永超 / 电子工业出版社 / 2017-5 / 89

《Spring Cloud微服务实战》从时下流行的微服务架构概念出发,详细介绍了Spring Cloud针对微服务架构中几大核心要素的解决方案和基础组件。对于各个组件的介绍,《Spring Cloud微服务实战》主要以示例与源码结合的方式来帮助读者更好地理解这些组件的使用方法以及运行原理。同时,在介绍的过程中,还包含了作者在实践中所遇到的一些问题和解决思路,可供读者在实践中作为参考。 《Sp......一起来看看 《Spring Cloud微服务实战》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具