OC
的一個主要特性Runtime
運行時特性馍盟,在日常開發(fā)中我們使用到的都是不可見的,還好官方提供了Runtime
(objc4
)源碼供開發(fā)者研究茧吊,我是小白贞岭,下面就開始邁出源碼探索的第一步八毯,源碼編譯。
一瞄桨、下載objc4-750话速,編譯解決報錯問題
1、進入源碼區(qū)芯侥,搜索objc4
并下載
同時下載objc4相關(guān)依賴dyld泊交、launchd、Libc柱查、libauto廓俭、libclosure、libdispatch唉工、libplatform研乒、libpthread、xnu
淋硝。放在方便操作的文件夾雹熬,方便搜索查找。
2谣膳、下載后解壓竿报,并打開工程,如下圖:
3继谚、運行工程編譯報錯如下:
報錯信息:
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
設(shè)置為Standard arcgutectures
4仰楚、解決問題后編譯,繼續(xù)報錯:
一看發(fā)現(xiàn)reason.h
頭文件沒找到犬庇,缺失依賴文件,在步驟1下載的文件中搜索sys/reason.h
文件侨嘀,加入即可臭挽。我們需要創(chuàng)建一個include
文件來存放這些缺失的依賴文件。
設(shè)置頭文件路徑:
搜索缺失文件:
添加頭文件后繼續(xù)編譯咬腕,繼續(xù)添加缺失文件……
5欢峰、添加的過程中發(fā)現(xiàn)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
打開連接復(fù)制源碼到新建文件举反,解決懊直,哭笑不得。最新的源碼居然缺少文件火鼻,還要在歷史版本庫找室囊。
編譯后pthread_machdep.h
文件報錯:
Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int’))
重復(fù)定義雕崩,注釋即可。
編譯繼續(xù)報錯:
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));
直接注釋掉就行。繼續(xù)編譯尝偎,問題繼續(xù)出現(xiàn)報錯:
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編譯出現(xiàn):
'isa.h' file not found
isa.h
文件在工程runtime
文件中復(fù)制粘貼到include
文件下即可致扯。
8肤寝、繼續(xù)編譯繼續(xù)報錯:'_simple.h' file not found 搜索文件添加。
9急前、編譯報錯:Use of undeclared identifier 'CRGetCrashLogMessage'醒陆。
解決方法:target -> Build Settings -> Preprocessor Macros
添加LIBC_NO_LIBCRASHREPORTERCLIENT
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
都刪了)
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
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)
里的內(nèi)容macosx.internal
改為macosx
13、編譯報錯:
error: no such public header file: '/tmp/objc.dst/usr/include/objc/ObjectiveC.apinotes'
解決方法:Target->Build Settings->Other Text-Based InstallAPI Flags
里的內(nèi)容設(shè)為空世吨;
把Text-Based InstallAPI Verification Model
里的值改為Errors Only
澡刹。
14、編譯報錯耘婚,額…… 居然編譯通過了罢浇。
二、添加Debug Target
1沐祷、添加一個target
取名為 objc-test
2嚷闭、引入頭文件#import <objc/message.h>
創(chuàng)建一個新類HBObject
,繼承自NSObject
類赖临。添加屬性胞锰,方法,并給屬性賦值兢榨,調(diào)用方法嗅榕。運行如下:
代碼:
#import <Foundation/Foundation.h>
#import <objc/message.h>
void hb_test_method(Class cla, SEL _cmd){
NSLog(@"我這個添加的方法被調(diào)用了");
}
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;
}
至此完成了源碼調(diào)試,編譯通過吵聪。
注意如果報錯:
Undefined symbol: _objc_opt_class
凌那,需要適配Mac系統(tǒng),project -> deployment target
Mac OS
選擇10.14