2016-03-03 64 views
5

我有一個輕微的問題,我不確定如何解決。使用ONLY_ACTIVE_ARCH在編譯本地計算機時沒有遇到編譯警告=否

在我們的多個項目中,我們希望將「將警告視爲錯誤」(GCC_TREAT_WARNINGS_AS_ERRORS)更改爲YES

我們也想離開的Xcode的默認項目設置「只建有源體系」(ONLY_ACTIVE_ARCH),以YES用於調試和NO發佈。

然而,這有一個主要缺點。代碼如...

NSUInteger bob = 12234; 
NSLog(@"bob %lu", bob); 

應該產生以下類型的警告(因此在我們的例子錯誤):類型NSUInteger「的

價值不應該被用來作爲格式參數; 添加一個顯式的「無符號長」,而不是

然而,當開發人員構建和本地測試,他們沒有遇到此警告/錯誤,但是當他們承諾我們的倉庫,我們的持續集成在命令行中運行xcodebuild遇到警告並且其構建失敗。這顯然很令人沮喪。

我認爲這與使用Xcode時構建的架構和使用命令行中的xcodebuild時的區別有關。

我已上載這裏的示例項目...

https://github.com/OliverPearmain/ArchitectureDependantCompileWarning

我已經包括2種方案。如果您使用「ArchitectureDependantCompileWarning」(使用Debug構建配置,因此使用ONLY_ACTIVE_ARCH==YES)編譯iPhone 6S模擬器,則不會收到警告,並且編譯正常。如果您使用「ArchitectureDependantCompileWarning-FAILS」方案(使用發佈版本配置並因此使用ONLY_ACTIVE_ARCH==NO),則會遇到警告並且編譯失敗。

我想以某種方式確保在爲模擬器構建ONLY_ACTIVE_ARCH==NO時始終遇到此警告。這可能嗎?

+0

我會認爲這是不可能的,但我可能是錯的。發生此警告是因爲在期望'unsigned long'時傳遞'unsigned int'。所以當'NSUInteger'是'unsigned long'時,它看起來都很好。我可以想象,如果標記文件無效(無論這可能意味着什麼),那麼可以調整構建過程以在成功構建結束時爲每個所需架構創建某種標記文件,並且版本控制會拒絕提交 - 如果標籤文件比所有源文件更新,那麼標籤文件是否有效?)。 –

+0

我一直能夠捕捉到這些的唯一方法是始終爲「通用iOS設備」構建,即使在調試模式下,它也具有與ONLY_ACTIVE_ARCH = NO相同的實際效果(據我所知)。但是如果你打算這麼做的話,那麼即使是在調試模式下,也可以爲所有拱形構建它,這顯然很不方便。也許調整你的本地單元測試目標(我假設開發者在本地運行之前運行)爲所有拱形構建? – Palpatim

+0

根據一些實際的建議,%zd將在任何體系結構上正確打印NSInteger並沒有警告,因此使用%zd將是一個好習慣。 – gnasher729

回答

1

原因是5s出現時字長的變化。換句話說,5S及以上的iPhone都有一個64位的處理器,而以前的所有iPhone都有一個32位的處理器。

下面是實際的typedef爲NSUInteger

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 
typedef long NSInteger; 
typedef unsigned long NSUInteger; 
#else 
typedef int NSInteger; 
typedef unsigned int NSUInteger; 
#endif 

可以看到,對於32位處理器,NSUInteger被明確定義爲unsigned int而對於64位處理器,NSUInteger是明確地維護作爲unsigned long

因此,看着這個代碼...

NSUInteger bob = 12234; 
NSLog(@"bob %lu", bob); 

對於4S,這NSLog具有失配,因爲NSUInteger被明確定義爲unsigned int和格式說明%luunsigned long。這種非常明顯的不匹配是32位處理器存在警告的原因。對於64位處理器來說,沒有不匹配,因此沒有警告。

警告中的建議修復假定您打算使用unsigned long。但是,這是另一種解決方案。

NSUInteger bob = 12234; 
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 
NSLog(@"bob %lu", bob); 
#else 
NSLog(@"bob %u", bob); 
#endif 

的底線是,你正在嘗試做的是產生一個不匹配的警告時沒有不匹配,既不恰當,也不可行的。

編輯:

這不是失配誤差不能表現爲一個警告/錯誤的情況。從字面上看,這不是一個錯配。出現此錯誤的唯一方法就是實際上存在不匹配。如果您針對NSUInteger的定義會在您提到的特定代碼中造成不匹配的體系結構構建,則只會有不匹配。已經有一個標準的方法來做到這一點:設置爲「僅限構建主動架構」爲您的所有方案

+0

沒錯,但這並不能回答如何在所有平臺上始終打開這些字長警告的問題。 – JAL

+0

我的鍵盤電池沒電了,我的答案在我完成之前就已經提交。我改變了電池,並完成了我的答案。 –

+0

我真的很感激你花時間爲了他人的利益而正確回答這個問題。然而,我完全意識到我描述的行爲背後的原因和歷史。我在我的OP中特別提出的要求是確保這種錯誤體現在那些比我更少的無知中,即使它們構建到某些模擬器時也是如此。 –