前言
工欲善其事必先利其器,所以,我们在探究runtime的时候总需要一些工具(调试),在查看网上相关文章资料后,发现时间上都比较古早,本着积累和给后续的小伙伴提供便利,我打算写一篇文章。当然时间紧急的可以直接滑到最后获取相关预制菜进行服用。
食材购买地址
首先我们需要从 Apple OSS Distributions 下载相关资源。
厨房等级
本文基于目前手头设备进行的编译调试
- macOS 版本 15.0.1
- Xcode 版本 16.1
食材清单
大家可以点击相关文字链接直达资源下载:
在后续的
Libc中pthread_machdep.h已被去掉的,所以在从Libc-Libc-825.40.1库添加。
我们按照上面图片将下载的资源解压放入goods文件夹中,方便搜索objc4里缺少的头文件。同时在项目内创建 dependency文件夹,用于存放确实文件。如下图
并且 在Build Settings -> Header Search Paths中添加此路径$(SRCROOT)/dependency,如图所示
食材处理
前期需要准备的内容我们就差不多准备好了,接下来打开objc4工程,然后打开objc.xcodeproj,然后选择objc这target编译一下,可以看到报错如下:
食材确实
unable to find sdk 'macosx.internal'
在Project->build setting->Base SDK,选择 macOS。依次对objc-evn和objc-trampolines进行修改
同时修改Run Script,修改objc的Run Script(markgc)脚本,将 macosx.internal 改成macosx。
注意是 Run Script(markgc)
在倒数第三个!!!!
配置菜品
在遇到报错的文件缺失,我们可以在终端输入
cd dependency
find . -name "xxxxx.h"
为了方便大家,这里我一一书写命令行,直接说明相关文件路径。遇到没有的文件夹,直接创建一个。
'sys/reason.h' file not found
打开xnu文件夹,然后在xnu/bsd/sys目录下找到reason.h文件,copy到 dependency/sys/文件夹下
'mach-o/dyld_priv.h' file not found
打开dyld文件夹,然后在dyld/include/mach-o目录下找到dyld_priv.h文件,copy到 dependency/mach-o/文件夹下
'os/lock_private.h' file not found
打开在libplatform文件夹,然后在libplatform/private/os目录下找到lock_private.h文件,copy到 dependency/sys/文件夹下
'os/variant_private.h' file not found
打开Libc文件夹,然后在Libc/os目录下找到variant_private.h文件,copy到 dependency/os/文件夹下
'os/base_private.h' file not found
打开xnu文件夹,然后在xnu/libkern/os/目录下找到base_private.h文件,copy到 dependency/os/文件夹下
'pthread/tsd_private.h' file not found
打开libpthread文件夹,然后在libpthread/private/pthread/目录下找到tsd_private.h文件,copy到 dependency/pthread/文件夹下
'machine/cpu_capabilities.h' file not found
打开xnu文件夹,然后在xnu/osfmk/machine/目录下找到cpu_capabilities.h文件,copy到 dependency/machine/文件夹下
'os/tsd.h' file not found
打开xnu文件夹,然后在xnu/libsyscall/os/目录下找到tsd.h文件,copy到 dependency/os/文件夹下
'System/pthread_machdep.h' file not found
打开Libc-825.40.1文件夹,然后在Libc-825.40.1/pthreads/目录下找到pthread_machdep.h文件,copy到 dependency/System/文件夹下
'System/machine/cpu_capabilities.h' file not found
打开xnu文件夹,然后在xnu/osfmk/machine/目录下找到cpu_capabilities.h文件,copy到 dependency/System/machine/文件夹下
注意
cpu_capabilities.h这里又加了一次,相同路径
'CrashReporterClient.h' file not found
打开Libc-825.40.1文件夹,然后在Libc-825.40.1/include/目录下找到CrashReporterClient.h文件,copy到 dependency/文件夹下
#include_next <CrashReporterClient.h> 这里报错
这里可以直接注释掉
'Block_private.h' file not found
打开libclosure文件夹,然后在libclosure/目录下找到Block_private.h文件,copy到 dependency/文件夹下
'objc-shared-cache.h' file not found
打开dyld文件夹,然后在dyld/include/目录下找到objc-shared-cache.h文件,copy到 dependency/文件夹下
'os/reason_private.h' file not found
打开xnu文件夹,然后在xnu/libkern/os/目录下找到reason_private.h文件,copy到 dependency/os/文件夹下
'os/bsd.h' file not found
打开Libc文件夹,然后在Libc/libdarwin/h/目录下找到bsd.h文件,copy到 dependency/os/文件夹下
'os/api.h' file not found
打开Libc文件夹,然后在Libc/os/目录下找到api.h文件,copy到 dependency/os/文件夹下
'os/linker_set.h' file not found
打开xnu文件夹,然后在xnu/bsd/sys/目录下找到linker_set.h文件,copy到 dependency/os/文件夹下
'_simple.h' file not found
打开libplatform文件夹,然后在libplatform/private目录下找到_simple.h文件,copy到 dependency/文件夹下
'kern/restartable.h' file not found
打开xnu文件夹,然后在xnu/osfmk/kern/目录下找到restartable.h文件,copy到 dependency/kern/文件夹下
食材处理
'os/feature_private.h' file not found
注释此头文件的引用
'os/log_simple_private.h' file not found
注释此头文件的引用
删除相关使用
dyld_priv.h中 Expected ','
删除dyld_priv.h的所有的bridgeos(3.0)(包括前面的','号)。
lock_private.h 中 expected ','
删除lock_private.h的所有的bridgeos(4.0)(包括前面的','号)。
Static declaration of '_pthread_has_direct_tsd' follows non-static declaration (pthread_machdep.h)
注释掉报错代码,如下图
Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0'
删除后面条件
// 修改前
bool willTerminate = (DebugPoolAllocation == Fatal
|| sdkIsAtLeast(10_12, 10_0, 10_0, 3_0, 2_0));
// 修改后
bool willTerminate = (DebugPoolAllocation == Fatal);
Use of undeclared identifier 'dyld_platform_version_macOS_10_13'
注释相关代码 如下图
variant_private.h 文件中报 error: expected ','
删除variant_private.h中所有的bridgeos(4.0)以及bridgeos相关内容(包括前面的','号)。
'malloc_private.h' file not found
注释掉相关 导入以及使用如下
第一步
第二步
第三步
Use of undeclared identifier 'dyld_fall_2020_os_versions'
错误内容包含了一些其他的
Use of undeclared identifier 'objc4'
Use of undeclared identifier 'classRxSigning'
Use of undeclared identifier 'classRoSigningFaults'
Use of undeclared identifier 'autoreleaseFaultsMacOS'
Use of undeclared identifier 'preoptimizedCaches'
老规矩 全部注释掉!!
'sandbox/private.h' file not found
注释注释注释!!
'Cambria/Traps.h' file not found
注释注释注释!!
Use of undeclared identifier 'CRSetCrashLogMessage'
注释注释注释!!
'Cambria/Cambria.h' file not found
注释注释注释!!
Use of undeclared identifier 'oah_is_current_process_translated'
修改如下
Library 'oah' not found
在 objc 这个 target 的 Build Settings 中,搜索 Other Linker Flags,然后在 debug 和release 中删除 -loah
到目前全部错误,我们就解决了,看到 build succeeded,悬着的心终于落下了!!
蒸煮炒
距离我们能成功调试代码就剩下最后这一步了,革命尚未成功,同志仍需努力!
锅碗
添加一个可供调试的target
步骤一
步骤二 起名
objcBuildDemo
瓢盆
添加相关依赖库 如下图所示
将Build Settings中将Enable Hardened Runtime设置为NO,否则在objc源码下的断点没法断住,这个是Xcode 11的新特性!!!
至此,我们完成了所有需要操作的一些内容,接下来我们可以尽情享用。
食用
准备碗筷
我们通过 command + N 创建调试文件 Animal 如下图
在main文件中进行初始化
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "Animal.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
Animal *obj = [[Animal alloc]init];
NSLog(@"%zd", class_getInstanceSize(obj.class));
}
return 0;
}
在如图处打上断点,选择target objcBuildDemo,运行
点击
step into就这样我们走进了objc 调试世界。
进食失败
筷子拿反
在运行的时候我们,可能遇到断点断不住的情况,这个时候,可能是我们的筷子拿反了,我们需要将他调换一下顺序。
将上图的两个位置进行调换,main 文件在上面即可继续服用!
and so on...
预制菜
为了方便大家更快享用,我将项目上传到了这里。时间不够的小伙伴,可以自取。 麻烦 star 一下哈,给个好评!