objc4-818.2 源码编译调试
在平常的开发中,我们都只是知道有 objc 这个框架,为我们提供了一些底层接口(例如 runtime 以及 objc_msgSend 等);如果我们能够将 objc 源码跑起来,加上 LLDB 进行调试,就能够清晰的分析整个代码的执行流程。
当前环境
- macOS 11.4 (MBP 2015)
- Xcode 12.5
- objc4-818.2
获取源码
源码可以从苹果开源官网直接下载回来
本来想试试最新的 objc4-824
的源码,但是下载的时候报错了,所以还是拿 818.2 版本来练手吧。
error message
Please report the missing source or broken link to opensource@apple.com
开始配置
- 解压下载好的
objc4-818.2.tar
- 打开 objc.xcodeproj 项目工程
- 将当前的 Scheme 设置为
objc
–>My Mac
unable to find sdk ‘macosx.internal’
PROJECTS
–>objc
–>Build Settings
, 将Base SDK
改成macOS
TARGETS
–>objc
–>Build Settings
, 将Base SDK
改成macOS
‘sys/reason.h’ file not found
- 下载 xnu-7195.81.3.tar.gz
- 在项目根目录新建一个文件夹(例如:MissFiles)
- 把
xnu-7195.81.3/bsd/sys/reason.h
文件复制到MissFiles/sys
目录下 - 设置头文件搜索路径:
TARGETS
–>objc
–>Build Settings
–>Header Search Paths
, 添加一条$(SRCROOT)/MissFiles
以下的报错处理方式和上面的处理方式相同, 都是拷贝对应的头文件到对应的目录下, 具体信息请参照下表:
错误描述 | 对应的资料 | 对应目录 | 备注 |
---|---|---|---|
‘sys/reason.h’ file not found | xnu-7195.81.3/bsd/sys/reason.h | MissFiles/sys/ | |
‘mach-o/dyld_priv.h’ file not found | dyld-851.27/include/mach-o/dyld_priv.h | MissFiles/mach-o/ | 拷贝后会报类似错误 /MissFiles/mach-o/dyld_priv.h:130:130: Expected ',' ,需要将 , bridgeos(3.0) 这个内容全部注释(删除) |
‘os/lock_private.h’ file not found | libplatform-254.80.2/private/os/lock_private.h | MissFiles/os/ | |
‘os/base_private.h’ file not found | libplatform-220.100.1/private/os/base_private.h | MissFiles/os/ | 注意这里下载的是 220.100.1 版本,因为后面更新的版本未提供该文件 |
‘pthread/tsd_private.h’ file not found | libpthread-454.100.8/private/pthread/tsd_private.h | MissFiles/pthread | |
‘pthread/spinlock_private.h’ file not found | libpthread-454.100.8/private/pthread/spinlock_private.h | MissFiles/pthread | |
‘System/machine/cpu_capabilities.h’ file not found | xnu-7195.81.3/osfmk/machine/cpu_capabilities.h | MissFiles/System/machine/ | |
‘os/tsd.h’ file not found | xnu-7195.81.3/libsyscall/os/tsd.h | MissFiles/os/ | |
‘System/pthread_machdep.h’ file not found | Libc-825.40.1/pthreads/pthread_machdep.h | MissFiles/System/ | 拷贝后会有 4 个地方报错,把报错的代码通通注释掉 |
‘CrashReporterClient.h’ file not found | Libc-825.40.1/include/CrashReporterClient.h | MissFiles/ | |
‘_simple.h’ file not found | libplatform-254.80.2/private/_simple.h | MissFiles/ | |
‘objc-shared-cache.h’ file not found | dyld-851.27/include/objc-shared-cache.h | MissFiles/ | |
‘Block_private.h’ file not found | libclosure-79/Block_private.h | MissFiles/ | |
‘kern/restartable.h’ file not found | xnu-7195.81.3/osfmk/kern/restartable.h | MissFiles/kern/ | |
‘os/linker_set.h’ file not found | Libc-1439.100.3/os/linker_set.h | MissFiles/os/ | |
‘os/feature_private.h’ file not found | 注释相关的引用 | ||
‘Cambria/Traps.h’ file not found | 注释相关的引用 | ||
‘Cambria/Cambria.h’ file not found | 注释相关的引用 | ||
‘objc-bp-assist.h’ file not found | 注释相关的引用 | ||
‘os/reason_private.h’ file not found | xnu-7195.81.3/libkern/os/reason_private.h | MissFiles/os/ | |
‘os/variant_private.h’ file not found | Libc-1439.100.3/os/variant_private.h | MissFiles/os/ | 拷贝后需要将 , bridgeos 和 , bridgeos(4.0) 注释掉 |
上面有些库并不是最新的,因为最新版的可能并未包含我们所需的头文件,所以你可以适当找老版本。如果你不知道确实的头文件在哪个库里面,你可以通过在谷歌中输入 xxx.h site:opensource.apple.com
来定向检索,或许能够直接定位到你需要的库。
需要注释的地方(大体思路就是不清楚你就注释就行了)
- oah_is_current_process_translated
- dyld_platform_version_macOS_10_13
- dyld_fall_2020_os_versions
- os_feature_enabled_simple(objc4, preoptimizedCaches, true)
- dyld_platform_version_macOS_10_11
- LINKER_SET_FOREACH
- dyld_fall_2018_os_versions
- sdkIsAtLeast(10_12, 10_0, 10_0, 3_0, 2_0)
- ‘_static_assert’ declared as an array with a negative size
libobjc.order 错误
ld: can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/AppleInternal/OrderFiles/libobjc.order
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/AppleInternal/OrderFiles/libobjc.order
- 找到
TARGETS
–>objc
–>Build Settings
–>Order File
- 把
Debug
的搜索路径改成$(SRCROOT)/libobjc.order
library not found for -loah
- 找到
TARGETS
–>objc
–>Build Settings
–>Other Linker Flags
- 把 Debug 和 Release 中的
-loah
都删掉
Xcode 编译脚本的错误
/Users/xiaopin/Downloads/objc4-818.2/xcodebuild:1:1: SDK "macosx.internal" cannot be located.
/Users/xiaopin/Downloads/objc4-818.2/xcrun:1:1: sh -c '/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -sdk macosx.internal -find clang++ 2> /dev/null' failed with exit code 16384: (null) (errno=No such file or directory)
/Users/xiaopin/Downloads/objc4-818.2/xcrun:1:1: unable to find utility "clang++", not a developer tool or in PATH
- 找到
TARGETS
–>objc
–>Build Phases
->Run Script(markgc)
- 把脚本的
macosx.internal
改成macosx
‘CrashReporterClient.h’ file not found
在上面明明把 CrashReporterClient.h
文件拷贝到 MissFiles 目录下了,但是还是报文件未找到的错误。
TARGETS
–>objc
–>Build Settings
–>Other Linker Flags
, 删除 Debug 和 Release 中的-lCrashReporterClient
Build Succeeded
经过上面繁琐的配置后,重新按下 command + B 进行编译,此时终于看到了久违的 Build Succeeded
,恭喜 🎉🎉🎉,我们已经离成功不远了。
调试源码
新建一个终端命令行程序,
File
–>New
–>Target...
–>macOS
–>Command Line Tool
, 我取名为MYTest
绑定二进制依赖
- 找到
TARGETS
–>MYTest
–>Build Phases
–>Dependencies
, 点击+
号把objc
添加进去 - 找到
TARGETS
–>MYTest
–>Build Phases
–>Link Binary Width Libraries
, 点击+
号把libobjc.A.dylib
添加进去
- 找到
新建一个
MYObject
类, 并修改 main.m 的代码#import <Foundation/Foundation.h> #import "MYObject.h" int main(int argc, const char * argv[]) { @autoreleasepool { MYObject *obj = [MYObject alloc]; } return 0; }
在 main.m 中打了断点,发现并不能断在断点处
- 找到
TARGETS
–>MYTest
–>Build Phases
–>Compile Source
- 把 main.m 拖到第一个位置
- 找到
好了,现在可以愉快地调试 objc 源码了 🎉🎉🎉
最后附上一张效果图
补上头文件 MissFiles.zip,请自取