学习OC底层,少不了要研究源码,今天就编译调试一下objc4-818.2 源码,探索OC底层。
准备工作
- mac OS 11.4
- Xcode 12.4
- objc4-818.2
objc4-818.2 下载地址
opensource.apple.com/
或者
opensource.apple.com/tarballs/
搜索objc
开始配置
直接编译遇到的问题
error: unable to find sdk 'macosx.internal' (in target 'objc-trampolines' from project 'objc') warning: Traditional headermap style is no longer supported; please migrate to using separate headermaps and set 'ALWAYS_SEARCH_USER_PATHS' to NO. (in target 'objc-trampolines' from project 'objc')
解决方法
- 系统要求的macOS版本需要处理
选择 target -> objc -> Build Settings -> Base SDK -> 选择 macOS 让系统给你进行匹配
注:需要修改objc和objc-trampolines两个target
选择 target -> objc -> Build Settings
搜索always 将ALWAYS_SEARCH_USER_PATHS 设置为NO
注:需要修改objc和objc-trampolines两个target
文件查漏补缺
准备好以下资源
'sys/reason.h' file not found
- 大家可以通过 Apple source 在 xnu-7195.101.1/bsd/sys/reason.h 路径自行下载
- 还可以通过谷歌中输入reason.h site:opensource.apple.com 定向检索
把找到的文件加入到工程里面。例如:
- 我在根目录创建了一个
OSCommon
文件 - 创建
sys
文件 - 把
reason.h
文件加入进去
目前还不行,一定给我们的工程设置文件检索路径
- 选择 target -> objc -> Build Settings
- 在工程的 Header Serach Paths 中添加搜索路径 $(SRCROOT)/OSCommon
上面的报错情况处理方式都是和 'sys/reason.h' file not found 一样的解决
文件补漏情况如下:
1.'sys/reason.h' file not found
xnu-7195.101.1/bsd/sys/reason.h 下载
2.'mach-o/dyld_priv.h' file not found
dyld-851.27/include/mach-o/dyld_priv.h 下载
3.'os/lock_private.h' file not found 'os/base_private.h' file not found
libplatform-220.100.1/private/os/lock_private.h 、base_private.h(220.100.1之后版本没有这个文件)
4.'pthread/tsd_private.h' file not found 'pthread/spinlock_private.h' file not found
libpthread-454.100.8/private/pthread/tsd_private.h、spinlock_private.h
5.'System/machine/cpu_capabilities.h' file not found
xnu-7195.101.1/osfmk/machine/cpu_capabilities.h
6.'os/tsd.h' file not found
xnu-7195.101.1/libsyscall/os/tsd.h
7.'System/pthread_machdep.h' file not found
最新版本没有这个文件,下载Libc-825.40.1 源码
Libc-825.40.1/pthreads/pthread_machdep.h
8.'CrashReporterClient.h' file not found
最新版本没有这个文件,下载Libc-825.40 源码
Libc-825.40.1/include/CrashReporterClient.h
9.'os/feature_private.h' file not found
删除#include <os/feature_private.h> // os_feature_enabled_simple()
10.'_simple.h' file not found
libplatform-220.100.1/private/_simple.h
11.'os/linker_set.h' file not found
Libc-1439.100.3/os/linker_set.h
12.'Cambria/Traps.h' file not found
删除掉
#if TARGET_OS_OSX
#include <Cambria/Traps.h>
#include <Cambria/Cambria.h>
#endif
复制代码
13.'kern/restartable.h' file not found
xnu-7195.101.1/osfmk/kern/restartable.h
14.'objc-shared-cache.h' file not found
dyld-851.27/include/objc-shared-cache.h
15.'objc-bp-assist.h' file not found
文件 objc-bp-assist.h 本应在 objc4-818.2 源码 中,但官方没有提供,所以只能在 objc-os.mm 文件中注释该引用!
16.'Block_private.h' file not found
libclosure-79 –> Block_private.h
17.'os/reason_private.h' file not found
xnu-7195.101.1/libkern/os/reason_private.h
18.'os/variant_private.h' file not found
Libc-1439.100.3/os/reason_private.h
缺失的library
library not found for -lCrashReporterClient
- 选择
target
->objc
->Build Settings
- 在
Other Linker Flags
中删除-lCrashReporterClient
(Debug
和Release
都删了)
library not found for -loah
- 选择
target
->objc
->Build Settings
- 在
Other Linker Flags
中删除-loah
(Debug
和Release
都删了)
错误处理
文件报错
1.dyld_priv.h
报错
去掉 bridgeos(3.0)
2.lock_private.h
报错
去掉bridgeos(4.0)
3.导入CrashReporterClient.h
报错
可以通过以下方式解决
- 需要在 Build Settings -> Preprocessor Macros 中加入:LIBC_NO_LIBCRASHREPORTERCLIENT
4.variant_private.h
报错
去掉错误处的bridgeos
5.其他错误
os_feature_enabled_simple()
注释了 feature_private.h 文件之后,某些地方使用的该文件的函数,也将报错
/objc4-818.2/runtime/objc-runtime.mm:451:10: error: use of undeclared identifier ‘os_feature_enabled_simple’
if (!os_feature_enabled_simple(objc4, preoptimizedCaches, true)) {
1 error generated.
对于未经声明的 os_feature_enabled_simple()
函数,只能注释!
/// objc-runtime.mm 文件的 void environ_init(void) 函数中
// DisablePreoptCaches = true;
// }
复制代码
2.Mismatch in debug-ness macros
注释掉
Use of undeclared identifier 'oah_is_current_process_translated'
复制代码
删除
#if TARGET_OS_OSX
if (oah_is_current_process_translated()) {
kern_return_t ret = objc_thread_get_rip(threads[count], (uint64_t*)&pc);
if (ret != KERN_SUCCESS) {
pc = PC_SENTINEL;
}
} else {
pc = _get_pc_for_thread (threads[count]);
}
#else
复制代码
4.在 objc-runtime.mm 文件的 void environ_init(void)
函数中找不到 dyld_fall_2020_os_versions 、objc4 、preoptimizedCaches 三个宏定义!
我们不妨现在 objc-runtime.mm 文件函数void environ_init(void)的上面声明这几个宏!
5.不被识别的宏定义 dyld_platform_version_
分析错误日志:发现是找不到定义的 dyld_platform_version_macOS_10_13!objc 项目中很多地方都要相关的宏定义 dyld_platform_version_ ,都会报错 use of undeclared identifier!
由于一些文件找不到的缘故,此处不得不使用旧版本的代码来处理,在 dyld_priv.h 文件定义几个相关宏:
#define DYLD_MACOSX_VERSION_10_11 0x000A0B00
#define DYLD_MACOSX_VERSION_10_12 0x000A0C00
#define DYLD_MACOSX_VERSION_10_13 0x000A0D00
#define DYLD_MACOSX_VERSION_10_14 0x000A0E00
复制代码
6.不匹配的函数
dyld_program_sdk_at_least()
既然 dyld_program_sdk_at_least() 函数不适配,继续使用老版本的判断方法:
/// if (!dyld_program_sdk_at_least(DYLD_MACOSX_VERSION_10_13)) {
if (!(dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13)) {
/// if (!dyld_program_sdk_at_least(dyld_platform_version_macOS_10_11)) {
if (!(dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_11)) {
复制代码
7.NsObject.h
Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0'
Use of undeclared identifier 'dyld_platform_version_iOS_10_0'
Use of undeclared identifier 'dyld_platform_version_macOS_10_12'
Use of undeclared identifier 'dyld_platform_version_tvOS_10_0'
Use of undeclared identifier 'dyld_platform_version_watchOS_3_0'
复制代码
注释掉
#define sdkIsAtLeast(x, i, t, w, b) \
(dyld_program_sdk_at_least(dyld_platform_version_macOS_ ## x) || \
dyld_program_sdk_at_least(dyld_platform_version_iOS_ ## i) || \
dyld_program_sdk_at_least(dyld_platform_version_tvOS_ ## t) || \
dyld_program_sdk_at_least(dyld_platform_version_watchOS_ ## w) || \
dyld_program_sdk_at_least(dyld_platform_version_bridgeOS_ ## b))
复制代码
修改为
#if TARGET_OS_OSX
# define DYLD_OS_VERSION(x, i, t, w, b) DYLD_MACOSX_VERSION_##x
# define sdkVersion() dyld_get_program_sdk_version()
#elif TARGET_OS_IOS
# define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##i
# define sdkVersion() dyld_get_program_sdk_version()
#elif TARGET_OS_TV
// dyld does not currently have distinct constants for tvOS
# define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##t
# define sdkVersion() dyld_get_program_sdk_version()
#elif TARGET_OS_BRIDGE
# if TARGET_OS_WATCH
# error bridgeOS 1.0 not supported
# endif
// fixme don't need bridgeOS versioning yet
# define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##t
# define sdkVersion() dyld_get_program_sdk_bridge_os_version()
#elif TARGET_OS_WATCH
# define DYLD_OS_VERSION(x, i, t, w, b) DYLD_WATCHOS_VERSION_##w
// watchOS has its own API for compatibility reasons
# define sdkVersion() dyld_get_program_sdk_watch_os_version()
#else
# error unknown OS
#endif
#define sdkIsOlderThan(x, i, t, w, b) \
(sdkVersion() < DYLD_OS_VERSION(x, i, t, w, b))
#define sdkIsAtLeast(x, i, t, w, b) \
(sdkVersion() >= DYLD_OS_VERSION(x, i, t, w, b))
// Allow bare 0 to be used in DYLD_OS_VERSION() and sdkIsOlderThan()
#define DYLD_MACOSX_VERSION_0 0
#define DYLD_IOS_VERSION_0 0
#define DYLD_TVOS_VERSION_0 0
#define DYLD_WATCHOS_VERSION_0 0
#define DYLD_BRIDGEOS_VERSION_0 0
复制代码
8.objc-runtime-new.mm
报错
'_static_assert' declared as an array with a negative size
复制代码
注释掉
libobjc.order
错误
can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/AppleInternal/OrderFiles/libobjc.order
复制代码
- 选择
target
->objc
->Build Settings
- 在工程的
Order File
中添加搜索路径$(SRCROOT)/libobjc.order
Xcode 脚本编译问题
SDK "macosx.internal" cannot be located.
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)
unable to find utility "clang++", not a developer tool or in PATH
复制代码
- 选择
target
->objc
->Build Phases
->Run Script(markgc)
- 把脚本文本
macosx.internal
改成macosx
长出一口气,编译成功了?
objc 编译调试
- 新建一个 Target : Test
File
-> New
->Target...
->macOS
->Applation
->Command Line Tool
- 绑定二进制依赖关系
- 运行代码进入源码,大家可以自由编译调试咯!
调试遇到的问题
打了断点以后发现无法断到断点处,这里我们进行一下处理,在Test
—Build Phases
—Complie Sources
中,把main.m
放到第一位
参考:
juejin.cn/post/684490…
www.jianshu.com/p/881a70537…
blog.csdn.net/cairo123/ar…