歡迎轉載,請保留出處:http://www.cnblogs.com/wellbye/
做windows開發幾年了,一直用vc。感覺這個集編輯、調試、管理於一體的IDE,確實是組織維護中小規模項目的利器。在使用的過程中,也積累了不少vc經驗技巧,甚至是習慣了那整套工作流程。當突然換到其它平台上開發時,面對新的系統和工具,總有點格格不入。比如說Mac上的xcode,也是一款全功能的IDE,但其在設計結構上與vc風格頗異,導致vcer在初步接觸的時候,不是覺得缺胳膊少腿,就是脫褲子放屁,明明看着就是一漂亮的花瓶,可就是摘不到花瓶里的花朵。但是功夫不負有心人,或是說大道外殊內同,終於讓我摸索出一條將xcode配置成vc style的方法,現在在兩個平台上開發都有體貼可人的IDE用,程序員的幸福莫過於此呀。
好了,開始正題,看vcer如何馴服xcode這匹小紅馬!(注:本文是寫給愛好vc的windows programmer看的,如果你本來就是mac或xcode的粉絲且不恥於MS的人品技術,那么請留步或是以批判的眼光來看待此文並歡迎指教)
首先介紹一下,我用vc是怎樣組織工程的。整個項目是一客戶端引擎,包括一系列功能庫,皆以vc project形式存在並被編譯成.lib靜態庫,另外有各種外殼(shell)程序,它們也是vc project但被編譯成.exe應用程序。上述所有vc project被組織在一個vc solution里。下面是一個簡單的示意圖:
另外分享幾個關於vc的小技巧:
1、使用vsprops文件來存放公用配置信息。vsprops文件是vc支持的一種配置文件,可認為是配置文件的頭文件。每個vc project都可以繼承一個vsprops配置文件,並且vsprops文件之間還可以繼承。我一般會配置兩個vsprops文件,一個叫depend.vsprops用來存公用配置,如第三方庫的頭文件和庫文件依賴路徑、自定義的預編譯宏、各project輸出的obj/lib/exe文件的位置;另一個叫spec.vsprops用來存每個開發者個人的配置,如整個第三方庫根目錄的路徑、某些特殊調試宏等。如下圖所示:
整個依賴關系為vc project -> depend.vsprops -> spec.vsprops。那么,有了兩個vsprops后,該怎么分別配置其中的內容呢?可以用兩個例子說明:
2、配置第三方庫依賴路徑。在我的項目里,第三方庫是個容量巨大的目錄,因為為了使用的方便,里面放的都是編譯好的頭文件和庫文件。不同的開發人員從Git倉庫中將其檢出后,可能會根據自己硬盤情況放到不同的位置。這時,可以在spec.vsprops中定義一個變量$(depend_dir)指向實際存放第三方庫的路徑,然后在depend.vsprops中利用繼承得到的$(depend_dir)來填寫對各種第三方庫的內部引用,如圖:
depend.vsprops中使用的是統一變量$(depend_dir),內容與個人無關,這個文件是要提交到倉庫里的。
spec.vsprops中的內容則是個人相關的,不用提交,因此每個人可隨意修改,也不會影響到他人和最終發布。
3、配置個人調試用的預編譯宏。有時候,某些功能會在發布版中關閉,但是為了調試方便,開發者會在自己機上編譯開發版時打開。這種功能的開關一般都是用宏來做條件編譯。因此,可以把開發者調試相關的宏定義在spec.vsprop中,而不是臨時去修改代碼,一旦忘記改回來又被提交的話,這些功能就不小心被放出去了。而使用vsprop的做法,只要保證發布機器上的spec.vsprop文件不被隨便修改,就不會誤發布任何功能。
4、要學會數數……
好了,說完vc,該介紹本文的主角xcode啦!先看一張圖,是上述solution在xcode里的組織結果:
先看一下vc與xcode之間有直觀對應的概念:
vc solution -> xcode workspace
vc project -> xcode project
vc configuration -> xcode scheme
vc vsprops -> xcode xcconfig
“一個大項目包含幾個小工程、大項目和小工程充滿各種神秘的配置選項”這個基本思路是一樣的,但差別也不少,講解如下:
1、首先xcode里把整個系統叫做workspace而非solution。在菜單欄File->New->Workspace即可新建一個這玩意,之后再用File->New->Project創建新工程時,記得在最后一步“Add to”選擇剛才新建的workspace。由於xcode里居然允許project之間互相嵌套,我實在不能理解這種做法有什么好處,為了與vc習慣保持一致,我們應在接下來的Group中選擇頂層項即讓此project“直轄”於workspace。
2、重復步驟1,將各個project輪流創建好后,會發現它們雜亂排成一列,這時出於視覺習慣要調整各project的上下順序,千萬要小心!如果你不是粗心或是超級快手,你應該會在放下的一瞬間發現彈出一個對話框,詢問里你是否要把project A添加到project B(A是你想要移動的,B是你想要移到它之后的),趕快點Cancel(希望你還沒有點OK)。其實這也是上面說過的project間可以互相嵌套功能的體現,只是在UI設計上,有個很不容易辨別的細節:你再拖動一下試試,這次注意觀察當你把A拖到B下方時,B下方邊框上會顯示一條粗線左端有一個圓圈,這時你保持水平左右移動一下,看到了什么沒有?那個圓圈會左右跳動!當它特別靠左時,才表示此次操作是要把A移到B下方,而它相對靠右時,表示的是把A加入B,也就是剛剛、一般人第一次都會做錯的操作!蛋疼了吧。。。
3、好了調整完順序,你可能會想像在vc里那樣,再建幾個filter(文件夾),把這些project分門別類放好。於是你右鍵點來點去,菜單項里找來找去,終於……沒找到!是的,xcode沒有這個功能!現在你知道為什么第2步那么重要了……
4、xcode project與vc project有一個最大的不同:一個vc project只能有一個輸出(lib、dll或是exe),但一個xcode project可以有多個輸出,每個輸出叫一個target,每個target都有一份獨立的完整的(project級的)配置。這些target可以是純邏輯上的划分,也可以是用來對應不同平台。我覺得這是個不錯的設計,比如一個project里面一些文件可以用來生成程序A,另一些文件用來生成程序B,這兩部份文件也有交集。如果是在vc里,那就只能配置成2個project了,或者為了完美解藕將公共部份再抽出來成1個project,2+1 project,簡稱3P……但在這個示例項目里,project已經划分得很細了,不存在上面說的情況。所以我也沒用到過在一個project中定義兩個不同邏輯target的功能。但是在上圖里,顯示testgui這個工程確實有2個target,那是因為跨平台的需要,我為每個project都定義了一個mac64 target和一個ios target。由於我並沒有支持ios emulator,否則的話還可以再添加第3個用於模擬器的target。
5、xcode project有哪些設置?首先,是屬於此工程的文件。文件不需要與工程在同目錄下,事實上我一般都會將代碼文件與IDE用的工程文件分開放,在solution里建一個build目錄,里面再為各IDE建相應子目錄。由於每個project會有多個target,因此針對每個文件還能單獨設置它屬於哪(幾)個target。利用這一點,可以將分屬於各個平台的源文件都添進來,方便查看編輯,同時為其設置適當的target屬性,也不會影響編譯。其實這個功能在vc中也有,利用vc和xcode這類IDE來查看源文件,可以方便的跳轉到各種聲明、定義中,比在ultraedit等普通編輯器里看要舒服多了。
下面是在vc里的設置。非win32平台相關的源文件全部打上了紅色減號,表示不被編譯。
下面是在xcode里設置文件屬性的面板,由於這個文件是屬於安卓平台的,因此兩個target前都沒有勾選。
在左側工程樹視圖中,除了看到所包含的源文件之外,還能看到各種依賴庫(Frameworks)、輸出文件(Products),初一看可能覺得有點亂,但其實也還不錯,與project有關的輸入輸出盡在眼底。但是Frameworks和Products下面的條目卻不像源文件一樣是直接通過右鍵菜單添加的,下面講工程設置時會解釋。
xcode project的設置,一共有四個優先級,從低到高分別是系統默認值、xc配置文件、project級配置、target級配置。比起vc來,多了project/target這兩級的差別,至於xc配置文件,也就相當於vsprops文件的性質。
點中project或target后,就會顯示其配置面板。大部份編譯相關選項都在Build Settings里,並且呈平板式顯示且右上角還有搜索功能,這比起VC的級聯配置菜單要輕爽得多。具體的選項就不多解釋了。下面說一下xcconfig文件的使用。使用的理由與vc同,都是希望將公共配置抽取出來,避免一經修改就要去大量的project里一個個手工調整。手動新建一個文本文件后綴改為.xcconfig放到workspace同級目錄。然后在各個project中通過右鍵菜單里的Add Files to選項把它加進來,之后轉到project級配置的info面板,第二欄Configurations里,有debug/Release兩項,再展開后又會分別列出所有target,也就是說針對每一個target的debug和release版,都可以單獨指定一個xcconfig文件。但沒有必要那么繁瑣,直接在debug/release這一級指定就可統一應用在所有target上。這里值得注意的是xcode里的Configuration與vc不一樣,xcode里指的就是xcconfig配置文件,而同樣的術語在vc中指的是debug/release/debug dll/release dll這類的整體編譯環境,vc中Configuration的范圍比xcode更大。
指定好xcconfig之后,來看一下這個文件里都能填些什么。先看下我填的內容:
EFFECTIVE_PLATFORM_NAME= FXROOT=$(SRCROOT)/../.. DEPROOT=$(FXROOT)/../fxd HEADER_SEARCH_PATHS[arch=armv6] = $(FXROOT) $(DEPROOT)/common $(DEPROOT)/iOS/include HEADER_SEARCH_PATHS[arch=x86_64] = $(FXROOT) $(DEPROOT)/common $(DEPROOT)/darwin/include /opt/local/include HEADER_SEARCH_PATHS[arch=i386] = $(FXROOT) $(DEPROOT)/common $(DEPROOT)/linux/include SYMROOT=~/fxo/xcode/bin/$(SDKROOT)/$(ARCHS) OBJROOT=~/fxo/xcode/obj/$(SDKROOT)/$(ARCHS) CONFIGURATION_BUILD_DIR=$(SYMROOT) LIBRARY_SEARCH_PATHS[arch=armv6] = $(inherited) $(SYMROOT) $(DEPROOT)/iOS/lib LIBRARY_SEARCH_PATHS[arch=x86_64] = $(inherited) $(SYMROOT) $(DEPROOT)/darwin/lib /opt/local/lib LIBRARY_SEARCH_PATHS[arch=i386] = $(inherited) $(SYMROOT) $(DEPROOT)/darwin/linux/lib /opt/local/lib OTHER_CFLAGS[sdk=iphone*] = -DTARGET_IPHONE=1 OTHER_CPLUSPLUSFLAGS[sdk=iphone*] = $(inherited) -x objective-c++
這里面包括:1)頭文件和庫文件搜索路徑,並且通過[arch=xxx]來區分不同架構;2)臨時和最終文件的輸出位置,這是通過SYMROOT和OBJROOT指定的。默認xcode會把輸出文件寫到它自己的安裝目錄下去,找起來不方便,所以我都會統一修改它們,但除了在這里定義輸出文件外,還需要在另一處修改:主菜單File->Workspace Settings->Build->Advanced,選中Legacy,也就是隨各target自定,即我們在xcconfig中指定的值;3)一些編譯選項,如宏、編譯器參數等。
6、把所有project配好后,那么就要設定其構建順序、產出、調試等等solution級的參數了。這一級在xcode里叫做scheme,一個scheme定義了一套project(target)的集合,相當於vc里的Configuration。在Manage Scheme面板上可以創建新的scheme,在創建scheme時需要指定一個target,也就是此scheme的最終輸出,這個target所屬的架構也就決定了此scheme的架構。不同架構的scheme有不同的運行調試環境,比如x64架構的shceme,就只能在64位mac上運行,而arm架構的則可以在iphone和ipad兩種設備以及相應的模擬器上運行(模擬器其實是i386架構的,這里的從屬關系和設計概念我還沒徹底搞清楚)。在添加完scheme時,記得把它的Container設成整個workspace而不是某個project,並且把后面的shared勾上,這樣這個scheme的信息會存在workspace下的xcsharedata子目錄里,把它提交到倉庫中,就可供所有人一起使用了。如果沒勾上shared,那么會存在xcuserdata里,這個目錄一般是不提交的,類似vc里每個project還會有一個$(machine).user后綴文件,里面存的也是不應提交的諸如調試時工作目錄、環境變量等信息的個人配置。
下面這個是Manage Scheme的界面,紅色標出了要特別去設的地方。
一旦把project和scheme都配好后,就可以舒舒服服享受IDE開發調試的方便和爽快了。看這張~
用過vc的人想必會有體會,當突然轉到命令行下工作,要用gdb這種看局部變量看源代碼都得敲命令的古老程序來調試時,那種世界末日的感覺吧。誠然人不能完全依靠工具,但也沒必要極端的回避工具。使用工具的目的也就是為了增加生產效率,當然是在深入理解工具背后原理的前提下。事實上我這個項目在所有平台都是可以用一套統一的makefile構建的(在windows下通過cygwin),包括ios和android。並且在初次接觸一個平台,在其上工作時,使用命令行式的簡單工具是非常必要的,因為這樣更有助於理解工作流程的本質。但是一旦這套機制清楚了,就沒必要困守成規,如果能尋找到一條更方便簡捷的途徑,又何樂不為呢。所以我才想在mac上對xcode一番探索,期間也在不少群和論壇上問過人,但得到的相當一部份答復不是說IDE都是浮雲,就是說別把windows的那一套帶到mac來,我只能笑而不語,個中艱辛雖不足道,但上面這段感觸就當是對之的回答和本文的總結吧~