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
app
四、解決問題後編譯,繼續報錯:ide
一看發現reason.h
頭文件沒找到,缺失依賴文件,在步驟1下載的文件中搜索sys/reason.h
文件,加入便可。咱們須要建立一個include
文件來存放這些缺失的依賴文件。 設置頭文件路徑:ui
搜索缺失文件:spa
添加頭文件後繼續編譯,繼續添加缺失文件……
五、添加的過程當中發現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;
}
複製代碼
至此完成了源碼調試,編譯經過。