故事背景
沒有無緣無故的重構,也沒有無緣無故的優(yōu)化玉控。故事的開始要追溯到我們的項目加了某個新功能。
在此之前座每,項目的編譯鏈接速度算是比較快前鹅,加上IDE編譯緩存的作用,不完全編譯的話峭梳,一般在10秒內就可以看到你修改的代碼的效果舰绘。但為了這項新功能,我們使用了某個第三方SDK葱椭,這個SDK是以framework的形式提供的捂寿。從此之后link階段的時間大大加長,大概需要五分鐘挫以。就算改一行代碼者蠕,也需要等三分鐘,喝上一杯茶之后才能看到代碼改動的效果掐松,大大影響了開發(fā)效率。產品的功能模塊較多粪小,很多其他模塊的開發(fā)者也深受荼毒大磺。
來看一下系統(tǒng)本身的一些framework的大小,系統(tǒng)相冊Photos.framework是115KB探膊,通訊錄動態(tài)庫AddressBook.framework是111KB杠愧,底層網絡處理庫CFNetwork.framework是295KB,等等逞壁。而我們使用的這個SDK流济,足足有400多MB!腌闯!所以鏈接速度巨慢也就不足為奇了绳瘟。下文將用slow.framework表示此SDK。
因為這項新功能是重點核心功能姿骏,而這個SDK也是我們調研比較之后最能滿足我們需求的服務提供方糖声,因此去除或者更換SDK都不太現實。
兼顧產品需求和開發(fā)效率分瘦,只能想辦法縮短編譯鏈接時間蘸泻。最直觀的想法是,只有真正開發(fā)該新功能模塊的才去link slow.framework嘲玫,而其他模塊的開發(fā)則不link它悦施,這樣大部分情況下的修改可以不受其影響。
因此我們的核心問題就是去团,如何選擇性地鏈接動態(tài)庫抡诞。
實踐
選擇性編譯
假設我們不鏈接slow.framework了穷蛹,那么使用到SDK中的接口的代碼,肯定是編譯不過的沐绒。因此在考慮怎樣選擇性鏈接framework之前俩莽,需要先修改代碼,使得用到slow.framework的接口的地方都能有選擇地被編譯乔遮。
添加一個Build Configuration扮超,叫Debug_Fast
這個Debug_Fast選項表示不使用slow.framework,為其添加一個預定義宏蹋肮,叫DEBUG_FAST
原來使用SDK的代碼都修改成這樣:
#ifndef DEBUG_FAST
// use slow.framework
#else
// balabala
#endif
這樣只有在定義了DEBUG_FAST之后出刷,我們就不再使用slow.framework中的代碼。
選擇性鏈接
在這個問題上坯辩,我們嘗試過兩種做法馁龟。
多scheme多target
具體步驟如下:
- 當前的項目只有一個target,可以duplicate出另一個target漆魔,我們暫且稱之為target_fast
- 修改target_fast中的Linked Frameworks and Libraries坷檩,將該slow.framework移除。
- 創(chuàng)建一個scheme改抡,這個scheme對應到的Executable是target_fast矢炼,并且對應的Build Configuration是我們之前添加好的Debug_Fast,我們稱之為scheme_fast阿纤。
這樣我們調試的時候句灌,選擇這個scheme_fast,就可以不鏈接slow.framework欠拾。
多scheme單target
上述的方法已經可以解決我們的問題胰锌,但是仍有一些副作用:
- 使用了多個target之后,以后我們每添加一個新文件藐窄,都需要將其加到兩個target中资昧,雖然Xcode會記住你的選擇,但還是很丑陋枷邪。
- 多個target對于以后的維護并不友好榛搔,要改一項配置也需要同步到兩個target中
因此我們最后采用了另外一種做法:多scheme單target,具體步驟如下:
- 先將slow.framework從Linked framework中移除
-
修改Other Linker Flags东揣,配置Debug和Release -link slow.framework践惑,而Debug_Fast則不鏈接
Paste_Image.png - 同上創(chuàng)建多個scheme,其中scheme_fast對應到Debug_Fast這個Build Configuration嘶卧。
這種解決方案更加簡單輕量尔觉,對原有項目的入侵也更少,更好維護芥吟。
<b>遇到難題不要抱怨侦铜,方法總比困難多专甩;解決了問題也不要輕易滿足,可能存在更優(yōu)雅的解決方案钉稍。</b>