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
搜索下面的项目: objc4
、 Libc
、 dyld
、 libauto
、 libclosure
、 libdispatch
、 libpthread
、 xnu
、 launchd
、 libplatform
,因为太新的版本没有我们需要的头文件,所以下载下面的版本即可:
objc4-709.1.tar.gz
、 Libc-825.40.1.tar.gz
、 dyld-421.2.tar.gz
、 libauto-77.1.tar.gz
、 libclosure-67.tar.gz
、 libdispatch-913.1.6.tar.gz
、 libpthread-301.1.6.tar.gz
、 xnu-4570.1.46.tar.gz
、 launchd-842.92.1.tar.gz
、 libplatform-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继续编译
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
然后选中TARGETS下的 debug-objc
,选择 Build Phases->Target Dependencies
,把 objc
的Target加进来。接着在 debug-objc/main.m
中添加你想调试的代码即可
四、结语
接下来就尽情的调试学习 objc
的源码吧,如果你想直接使用编译好的版本,点击 Github objc-709 下载即可。
以上所述就是小编给大家介绍的《objc - 编译Runtime源码objc4-709》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Golang源码探索(一) 编译和调试源码
- 写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实 原 荐
- JVM源码分析-JVM源码编译与调试
- 使用源码编译Hadoop
- Runtime源码编译
- 下载编译AOSP源码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
构建之法(第二版)
邹欣 / 人民邮电出版社 / 2015-7 / 59
软件工程牵涉的范围很广, 同时也是一般院校的同学反映比较空洞乏味的课程。 但是软件工程的技术对于投身IT 产业的学生来说是非常重要的。作者邹欣有长达20年的一线软件开发经验,他利用业余时间在数所高校进行了长达6年的软件工程教学实践,总结出了在16周的时间内让同学们通过 “做中学 (Learning By Doing)” 掌握实用的软件工程技术的教学计划,并得到高校师生的积极反馈。在此基础上,作者对......一起来看看 《构建之法(第二版)》 这本书的介绍吧!