1. 程式人生 > >iOS "Warning" No such file or directory詳解、解決方案和原理

iOS "Warning" No such file or directory詳解、解決方案和原理

最近用XCode做了一個靜態庫,在自己電腦上別的App project中編譯使用沒有任何問題,但是傳給別的同事使用在編譯的時候就會出現類似於下面警告。 warning: (i386) /UsersLibrary/Developer/Xcode/DerivedData/ProjectName-ebyadedaazwurqcvfzmyzzacvlbg/Build/Intermediates/ ProjectName.build/Debug-iphonesimulator/ProjectName.build/Objects-normal/i386/ClassName.o unable to open object file 通過在Google裡面搜尋,終於弄明白了,通過在XCode裡面將Generate Debug Symbol的值設為NO,重新編譯一下生成靜態庫,這次編譯出來的靜態庫再也不會產生已經警告了。這是為什麼呢? 在開始解釋原因之前,我們需要看一下什麼是Debug Symbol / Debug Information
1) Debug Symbol(除錯符號)

debug symbol is information that expresses which programming-language constructs generated a specific piece of machine code in a given executable module. Sometimes the symbolic information is compiled together with the module's binary file, or distributed in separate file, or simply discarded during the 

compilation and/or linking. This information enables a person using a symbolic debugger to gain additional information about the binary, such as the names of variables and routines from the original source code. This information can be extremely helpful while trying to investigate and fix a crashing
 application or any other fault.

When debug symbols are embedded in the binary itself, the file can then grow significantly larger (sometimes by several megabytes). To avoid this extra size, modern compilers and early mainframe debugging systems output the symbolic information into a separate file; for Microsoft compilers, this file is called a PDB file. Some companies ship the PDB on their CD/DVD to enable troubleshooting and other companies (like Microsoft, and the Mozilla Corporation) have special online servers from which it's possible to download the debug symbols separately. 

我簡單翻譯下上面兩段話

除錯符號(debug symbol)是代表在給定的可執行的模組中由程式語言產生的一段特定的機器碼的資訊。有時這些符號資訊被編譯進模組的二進位制檔案中,或者以單獨的檔案的形式進行分發,或者在編譯/連結的時候直接丟棄。這些資訊使得人們可以一種符號除錯程式來獲取關於二進位制檔案的額外資訊,比如變數的名稱和來自於原始碼的routines(不知道怎麼翻譯比較好)。這些資訊在我們研究和修復程式的崩潰問題或者別的錯誤的時候非常有用。

-----------------------為什麼會非常有用呢?----------------------------

因為藉助符號除錯程式可以將類似

Thread 0 Crashed:
0 libobjc.A.dylib 0×300c87ec 0×300bb000 + 55276
1 MobileLines 0×00006434 0×1000 + 21556
2 MobileLines 0×000064c2 0×1000 + 21698
3 UIKit 0×30a740ac 0×30a54000 + 131244

的log資訊轉換成

Thread 0 Crashed:
0 libobjc.A.dylib 0×300c87ec objc_msgSend + 20
1 MobileLines 0×00006434 -[BoardView setSelectedPiece:] (BoardView.m:321)
2 MobileLines 0×000064c2 -[BoardView touchesBegan:withEvent:] (BoardView.m:349)
3 UIKit 0×30a740ac -[UIWindow sendEvent:] + 264

-------------------這樣應該能非常明瞭地指出問題所在吧?-------------------

當除錯符號被嵌入進二進位制檔案本身的時候,檔案的尺寸會顯著地增長(不難理解吧?檔案中放入了額外的資訊,自然就大了)。為了避免這個額外的檔案尺寸(為什麼要避免,應該不難理解吧),現在的編譯器(新的,和老舊的相對)和早期的大型機除錯系統將符號資訊輸出到單獨的檔案中(為什麼要輸出到單獨的檔案中?除錯符號資訊對於普通的使用者是沒有用的,它只對開發人員追蹤問題有用,嵌入到二進位制檔案中只會增大檔案尺寸,延長使用者下載的時間,而且也會暴露你程式的內部資訊,如果你想保護你的程式碼不被別人猜到,你應該考慮不要在二進位制檔案中包含除錯資訊)。比如微軟的編譯器,這個檔案叫做PDB檔案,有的公司通過CD/DVD的方式來傳輸,有的公司提供線上的伺服器單獨進行下載,通過PDB檔案,你可以進行程式故障診斷(發現程式出錯的地方)。

通過上面簡單的介紹,我想大家應該對Debug Symbol應該已經有了個大概的認識了。

2)DWARF

接下來我們看看DWARF是什麼。  官方網站:http://dwarfstd.org/

官方網站對DWARF的簡單介紹:

DWARF is a debugging file format used by many compilers and debuggers to support source level debugging. It addresses the requirements of a number of procedural languages, such as C, C++, and Fortran, and is designed to be extensible to other languages. DWARF is architecture independent and applicable to any processor or operating system. It is widely used on Unix, Linux and other operating systems, as well as in stand-alone environments.  

DWARF是一種被眾多編譯器和偵錯程式使用的用於支援原始碼級別除錯的除錯檔案格式。它滿足了許多程式語言的需求,比如C,C++和Fortran,而且被設計成可拓展到其它語言。DWARF是平臺獨立的且適用於任何處理器任何作業系統。 DWARF廣泛應用於Unix,Linux和其它作業系統,以及獨立的環境中。

為了更好地理解DWARF,可以閱讀下這篇文章:http://lapcatsoftware.com/blog/2008/03/09/stabs-is-deprecated/  由於篇幅的原因原文就不貼過來了,直接簡單翻譯下。

2008-02-27開始, STABS(一種除錯資料格式)被蘋果Apple棄用。XCode專案build setting中DEBUG_INFORMATION_FORMAT預設的STABS被取代。

通過STABS, 你可以建立帶有除錯符號(debugging symbols)的程式的release版本,拷貝一份可執行程式MyApp.app/Contents/MacOS/MyApp儲存起來, 而把此可執行檔案除去除錯符號用於分發(strip the executable for shipping), 然後用未除去除錯符號的可執行程式來進行崩潰分析。和STABS不同, DWARF不將除錯符號包含到可執行檔案自身裡面,而是僅在可執行檔案裡包含對中間物件檔案的引用( references to the intermediate object files),而這些中間物件檔案中則包含著除錯符號。通常你可以在build/MyApp.build目錄的子目錄下找到這些中間物件檔案(.o files,如果你使用XCode,這些檔案則通常在/Developer/XCode/DerivedData/MyApp-****/Build/Intermediates目錄下)。如果你在使用DWARF編譯後刪除這些物件檔案,你將不能對你的程式碼進行單步除錯。 (如果你使用stabs, 這些物件檔案則是完全無用的.) 如果你把除錯符號從你的程式中除去(strip debugging symbols from your app),你也不能進行單步除錯,因為可執行檔案中已經不存在對中間物件檔案的引用了。

3)dSYM

為了避免進行stripping操作後除錯符號的丟失,你可以使用dwarf-with-dsym選項. DWARF with dSYM 選項在標準的DWARF之外執行一個額外的步驟:建立一個單獨的MyApp.app.dSYM檔案,這個檔案包含你的程式的所有除錯符號(這個檔案其實是一個包,可以通過右鍵->顯示包內容進行檢視)。事實上,DWARF with dSYM選項允許你對你進行單步除錯而不管可執行程式是否被剝離了除錯資訊(stripped)。這是可能的,這是因為gdb將會在你的程式的目錄下查詢.dSYM檔案。它不需要知道物件檔案(object files)的名字或者路徑。如果你不除去除錯符號 (strip debugging symbols), 你可以使用.o或者.dSYM檔案來除錯。

4.其它

其實如果,你想跟深入的瞭解,你可以更深入的瞭解DWARF除錯格式”,如果有什麼不同的見解,可以留言相互學習