# 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 <objc/message.h>`创建一个新类`HBObject`，继承自`NSObject`类。添加属性，方法，并给属性赋值，调用方法。运行如下：

![输入图片说明](https://images.gitee.com/uploads/images/2019/0719/161103_a0847f80_766685.jpeg "objc_test.jpeg")

代码：
```
#import <Foundation/Foundation.h>
#import <objc/message.h>

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;
}
```
