本節書摘來自異步社群《c程式設計新思維》一書中的第1章,第1.2節,作者 【美】ben klemens,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
在多數系統中,c享有一個中心的、貴賓禮遇的地位,以至于所有其他工具都處于從屬的地位;但是在windows機器中,c語言卻被奇怪地忽略了。
是以我不得不花點時間讨論如何來準備好一台windows機器以便用來寫c程式。如果你現在不需要在windows機器上程式設計,你可以直接跳到“1.3庫的路徑”。
這并非是針對microsoft的,請不要用這樣的角度來了解這一節。我無意去推測microsoft的動機和商業戰略。不過,如果你想在windows機器上用c來工作,你需要知道實際狀況(坦白地說,是不太友好)以及如何應對。
因為c和unix是共同進化的,很難在談到其中一個的時候不提及另一個。我個人認為從posix開始會比較容易些。并且,讀者中那些希望在windows機器上編譯來自其他環境的代碼的人會發現這麼講述也很自然。
總的來說,檔案系統的世界可以(稍微有點重疊地)分為兩個陣營:
posix相容系統
windows作業系統族
posix相容并不一定意味着整個系統的外觀和使用習慣都和unix機器一樣。比如,典型的mac使用者并不會意識到他們正在用一個界面漂亮的标準bsd系統,但是知道這一點的使用者可以到accessories->uilities目錄中,打開terminal程式,并為他們心儀的内容運作ls、grep和make。
說實話,我懷疑很多系統是不是真的100%符合标準的要求(比如要具備一個fortran′77編譯器)。為了我們的目的,我們需要一個可以像posix shell那樣運作的shell程式、一堆工具(sed、grep、make等)、一個c99編譯器,以及一些标準c庫之外的附加庫,比如fork和iconv。這些都可以被添加進主系統。包管理器相關的腳本、autotools和幾乎所有的編寫可移植代碼的工具都在某種程度上依賴于上面這些工具,是以即便你不想整天盯着指令行,安裝那些工具也是會帶來一些友善的。
在伺服器級的作業系統和windows 7的全功能版本中,microsoft提供了一個叫作sua的子系統(subsystem for unix-based application)——該系統以前稱為interix,用來提供通常的posix系統調用、korn shell,以及gcc。這個子系統一般并不是預設提供的,但是可以作為一個插件安裝。但是在其他的windows版本,包括windows 8上,并不提供sua,是以我們不能依賴microsoft為它自己的作業系統提供一個posix子系統。
既然這樣,可以嘗試cygwin。
如果你計劃從頭編譯安裝cygwin,你需要按照下面的步驟進行:
1. 寫一個windows下的c庫,在該庫中提供所有的posix函數。這需要你抹平一些windows和posix系統之間的差異性,比如windows中使用明确的盤符(例如:c:),而posix采用一個統一的檔案系統。在這種情況下,需要為c:與 /cygdrive/c,d:與 /cygdrive/d等等路徑表達之間建立别名。
2. 然後你就可以通過連接配接這個庫來編譯posix标準的程式了,可以嘗試:制作一個windows版本的ls、bash、grep、gcc、x、rxvt、libglib、perl、python,等等。
3. 一旦你已經編譯了幾百個程式和庫,就需要安裝一個包管理器以便使用者可以從中選擇需要安裝的元件。
microsoft在visual studio中提供了一個c++編譯器,并相容ansi c。這是microsoft提供的唯一一種編譯c代碼的途徑了。很多microsoft人士明确表示,對c99的支援是不會發生的(更别談支援c11了)。visual studio是主流編譯器中唯一至今還停留在c89标準的,是以我們必須從别處找到一個替代品。當然,cygwin提供了gcc,如果你遵從并安裝了cygwin,那麼你已經具有了一個完整的編譯環境。
如果你在cygwin下編譯,程式就将依賴于cygwin的庫來提供posix函數,即cygwin.dll(不管你的代碼實際上是否包含任何posix調用)。如果是在一台安裝了cygwin的機器上運作你的程式,那當然不會有問題。使用者自然可以點選可執行檔案并按照期望的行為運作,因為系統能夠找到cygwin的動态連結庫。如果你随程式釋出了cygwin1.dll,cygwin編譯的程式也可以在沒有cygwin的情況下運作。
在我的機器上,cygwin的路徑是/bin/cygwin1.dll。cygwin1.dll檔案有一個與gpl版權類似的授權(見“前言”),是以如果你從cygwin中剝離釋出dll庫,你必須釋出你自己程式的源代碼[2]。如果這對你是一個問題,那麼就必須找到一個不依賴于cygwin1.dll的編譯自己程式的方法,比如從代碼中移除所有posix标準的函數然後使用後面将要讨論的mingw。可以用cygcheck工具來找出程式所依賴的dll,驗證所生成的可執行檔案是否連接配接了cygwin1.dll。
如果你的程式不需要posix函數(比如fork或popen之類),那麼你可以用mingw(minimalist gnu for windows),它提供了一個标準的c編譯器和一些基礎工具。msys是與mingw伴生的,提供了另外的一些工具,例如shell。
缺少posix風格的外表并不是mingw的真正問題。msys提供了一個posix shell,或者幹脆忘掉指令行并嘗試一下code::blocks,這是一個在windows上使用mingw的ide內建環境。eclipse是一個功能更加豐富的可以配置為與mingw一起工作的ide內建環境,雖然這需要一點配置工作。
不過如果posix指令行能讓你感覺更舒服些,那就安裝cygwin,下載下傳提供mingw版本的gcc,用這些編譯環境而不是用與posix連接配接的、預設版本的cygwin gcc。
如果你還沒有遇到過autotools,那也快了。編譯包的三個标志性指令:./configure、make和make install。msys為這樣管理包提供了足夠的機制。如果你已經下載下傳了從cygwin的指令行編譯的包,那你可以用下面的指令來配置這個包,使用cygwin的mingw32編譯器來産生與posix無關的代碼:

然後像通常那樣運作make和make install。
在mingw下編譯後,不管是通過指令行還是autotools,你都會得到一個windows本地的二進制代碼。因為mingw并不知道cygwin1.dll的存在,你的程式并不會有任何posix調用,你得到的将是一個真正的windows程式,沒有人會知道你是從posix環境編譯出來的。
然而,mingw的真正問題是缺乏預編譯庫[3]。如果你想擺脫cygwin1.dll,那麼你也不能使用與cygwin一起發行的libglib.dll版本。你将必須從源代碼重新編譯glib成一個windows dll——但是glib在國際化方面依賴gnu的gettext,是以你将先把那個庫編譯一遍。現代代碼依賴于現代的庫,是以你可能會發現自己花費了很多時間來處理類似的工作,而在别的系統上可能隻是一行包管理器的指令。如果這樣,我們就真的如某些人所說,c已經40歲了,你需要從頭寫每樣東西。
是以,下面就是幾句忠告。microsoft已經離開了對話,任由其他人實作後grunge時代[4]的c編譯器。cygwin完成了這些工作并提供了全功能的包管理器,帶有可以滿足你的多數或全部工作的足夠多的庫,但這些都是伴随着posix風格的代碼和cygwin的dll的。如果你覺得這是一個問題,那麼你将不得不多做很多工作,以重建那些你體面的代碼所需要的整個環境和庫。