OC
的一个主要特性Runtime
运行时特性,在平常开发中咱们使用到的都是不可见的,还好官方提供了Runtime
(objc4
)源码供开发者研究,我是小白,下面就开始迈出源码探索的第一步,源码编译。ios
源码地址git
一、进入源码区,搜索objc4
并下载macos
同时下载objc4相关依赖dyld、launchd、Libc、libauto、libclosure、libdispatch、libplatform、libpthread、xnu
。放在方便操做的文件夹,方便搜索查找。api
二、下载后解压,并打开工程,以下图:xcode
三、运行工程编译报错以下:bash
报错信息: 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
markdown
四、解决问题后编译,继续报错:app
一看发现reason.h
头文件没找到,缺失依赖文件,在步骤1下载的文件中搜索sys/reason.h
文件,加入便可。咱们须要建立一个include
文件来存放这些缺失的依赖文件。 设置头文件路径:ide
搜索缺失文件:oop
添加头文件后继续编译,继续添加缺失文件……
五、添加的过程当中发现pthread_machdep.h
在依赖中没有,CrashReporterClient.h
也没有找到,也不知道在哪一个库,一脸懵逼,直接谷歌找到链接:
opensource.apple.com/source/Libc…
opensource.apple.com/source/Libc…
打开链接复制源码到新建文件,解决,啼笑皆非。最新的源码竟然缺乏文件,还要在历史版本库找。
编译后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
中全部的错误信息。
六、编译报错: 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 复制代码
问题解决。
七、接着步骤6编译出现: 'isa.h' file not found isa.h
文件在工程runtime
文件中复制粘贴到include
文件下便可。
八、继续编译继续报错:'_simple.h' file not found 搜索文件添加。
九、编译报错:Use of undeclared identifier 'CRGetCrashLogMessage'。
解决方法:target -> Build Settings -> Preprocessor Macros
添加LIBC_NO_LIBCRASHREPORTERCLIENT
十、编译报错:
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
都删了)
十一、编译报错:
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
十二、编译报错:
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
1三、编译报错:
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
。
1四、编译报错,额…… 竟然编译经过了。
一、添加一个target
取名为 objc-test
二、引入头文件#import <objc/message.h>
建立一个新类HBObject
,继承自NSObject
类。添加属性,方法,并给属性赋值,调用方法。运行以下:
代码:
#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; } 复制代码
至此完成了源码调试,编译经过。
注意若是报错:
Undefined symbol: _objc_opt_class
,须要适配Mac系统,project -> deployment target
Mac OS
选择10.14