# objc4-750 #### 介绍 objc4-750源码编译,调试通过的代码 `OC`的一个主要特性`Runtime`运行时特性,在日常开发中我们使用到的都是不可见的,还好官方提供了`Runtime`(`objc4`)源码供开发者研究,我是小白,下面就开始迈出源码探索的第一步,源码编译。 **源码地址:https://opensource.apple.com/tarballs/** #### 一、下载objc4-750,编译解决报错问题 1、进入源码区,搜索`objc4`并下载 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160158_606edfab_766685.jpeg "objc4.jpeg") 同时下载objc4相关依赖`dyld、launchd、Libc、libauto、libclosure、libdispatch、libplatform、libpthread、xnu`。放在方便操作的文件夹,方便搜索查找。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160306_b18f17d8_766685.jpeg "dependent.jpeg") 2、下载后解压,并打开工程,如下图: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160356_694c0b32_766685.jpeg "project.jpeg") 3、运行工程编译报错如下: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160422_0bf455fc_766685.jpeg "error.jpeg") 报错信息: **error: The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture. (in target 'objc') error: The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture. (in target 'objc-trampolines')** 解决方法:`target-Build Settings -Architecture`设置为`Standard arcgutectures` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160520_e6f2b8ef_766685.jpeg "architectures.jpeg") 4、解决问题后编译,继续报错: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160549_4ebbe0d3_766685.jpeg "reasonerror.jpeg") 一看发现`reason.h`头文件没找到,缺失依赖文件,在步骤1下载的文件中搜索`sys/reason.h`文件,加入即可。我们需要创建一个`include`文件来存放这些缺失的依赖文件。 设置头文件路径: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160628_afa73115_766685.jpeg "header.jpeg") 搜索缺失文件: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160655_e9cc6775_766685.jpeg "find.jpeg") 添加头文件后继续编译,继续添加缺失文件…… 5、添加的过程中发现`pthread_machdep.h`在依赖中没有,`CrashReporterClient.h`也没有找到,也不知道在哪个库,一脸懵逼,直接谷歌找到连接: https://opensource.apple.com/source/Libc/Libc-825.24/pthreads/pthread_machdep.h https://opensource.apple.com/source/Libc/Libc-825.26/include/CrashReporterClient.h 打开连接复制源码到新建文件,解决,哭笑不得。最新的源码居然缺少文件,还要在历史版本库找。 编译后`pthread_machdep.h`文件报错: Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int’)) 重复定义,注释即可。 编译继续报错: **Static declaration of '_pthread_getspecific_direct' follows non-static declaration** 注释掉`pthread_machdep.h`中所有的错误信息。 6、编译报错: **Expected ','** ``` extern bool dyld_program_minos_at_least(dyld_build_version_t version) __API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0), bridgeos(3.0)); ``` 直接注释掉就行。继续编译,问题继续出现报错: **Use of undeclared identifier 'DYLD_MACOSX_VERSION_10_14'** 在`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 ``` 问题解决。 7、接着步骤6编译出现: **'isa.h' file not found** `isa.h`文件在工程`runtime`文件中复制粘贴到`include`文件下即可。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160732_313a7a1c_766685.jpeg "isa.jpeg") 8、继续编译继续报错:**'_simple.h' file not found** 搜索文件添加。 9、编译报错:**Use of undeclared identifier 'CRGetCrashLogMessage'**。 解决方法:`target -> Build Settings -> Preprocessor Macros` 添加`LIBC_NO_LIBCRASHREPORTERCLIENT` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160813_19e9966d_766685.jpeg "preprocessor.jpeg") 10、编译报错: **clang:-1: linker command failed with exit code 1 (use -v to see invocation) no such file or directory: 'lCrashReporterClient'** 解决方法:在 `Build Settings -> Linking -> Other Linker Flags`里删掉`"-lCrashReporterClient"`(`Debug`和`Release`都删了) ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160848_4cb9d267_766685.jpeg "ICrashReporter.jpeg") 11、编译报错: **ld: can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/AppleInternal/OrderFiles/libobjc.order clang: error: linker command failed with exit code 1 (use -v to see invocation)** 解决方法: `Build Settings->Linking->Order File` 改成`$(SRCROOT)/libobjc.order` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160919_77bbc5d0_766685.jpeg "libobjc.jpeg") 12、编译报错: **Showing All Messages /xcodebuild:-1: SDK "macosx.internal" cannot be located. /xcrun:-1: unable to find utility "clang++", not a developer tool or in PATH** 解决方法:将`Target->Build Phases->Run-Script(markgc)`里的内容`macosx.internal`改为`macosx` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/160947_b71485ec_766685.jpeg "macosx.jpeg") 13、编译报错: **error: no such public header file: '/tmp/objc.dst/usr/include/objc/ObjectiveC.apinotes'** 解决方法:`Target->Build Settings->Other Text-Based InstallAPI Flags`里的内容设为空; 把`Text-Based InstallAPI Verification Model`里的值改为`Errors Only`。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/161014_7bd172a2_766685.jpeg "ObjectiveC.apinotes.jpeg") 14、编译报错,额…… 居然编译通过了。 #### 二、添加Debug Target 1、添加一个`target`取名为 `objc-test` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/161042_bf2ed499_766685.jpeg "objctest.jpeg") 2、引入头文件`#import `创建一个新类`HBObject`,继承自`NSObject`类。添加属性,方法,并给属性赋值,调用方法。运行如下: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/161103_a0847f80_766685.jpeg "objc_test.jpeg") 代码: ``` #import #import void hb_test_method(Class cla, SEL _cmd){ NSLog(@"我这个添加的方法被调用了"); } int main(int argc, const char * argv[]) { @autoreleasepool { Class HBObject = objc_allocateClassPair(objc_getClass("NSObject"), "HBObject", 0); class_addIvar(HBObject, "name", sizeof(id), log2(sizeof(id)), @encode(id)); class_addMethod(HBObject, sel_registerName("hb_test_method"), (IMP)hb_test_method, "v@:"); objc_registerClassPair(HBObject); id newObject = [[HBObject alloc]init]; [newObject setValue:@"yahibo" forKey:@"name"]; NSLog(@"name:%@",[newObject valueForKey:@"name"]); objc_msgSend(newObject,sel_registerName("hb_test_method")); } return 0; } ```