objc - 编译Runtime源码objc4-709

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

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

查看所有标签

猜你喜欢:

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

实战Java高并发程序设计

实战Java高并发程序设计

葛一鸣、郭超 / 电子工业出版社 / 2015-10-1 / CNY 69.00

在过去单核CPU时代,单任务在一个时间点只能执行单一程序,随着多核CPU的发展,并行程序开发就显得尤为重要。 《实战Java高并发程序设计》主要介绍基于Java的并行程序设计基础、思路、方法和实战。第一,立足于并发程序基础,详细介绍Java中进行并行程序设计的基本方法。第二,进一步详细介绍JDK中对并行程序的强大支持,帮助读者快速、稳健地进行并行程序开发。第三,详细讨论有关“锁”的优化和提高......一起来看看 《实战Java高并发程序设计》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

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

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具