天天看點

Gnu系統

原文轉自:http://blog.csdn.net/itianyi/article/details/43057279

前言:

很多時候,出現一些類似GNU,GCC,CLANG,LLVM等與編譯器有關的名詞的時候,都不太清楚它到底是幹嘛的,了解這些東西後,

對于xcode中很多配置型的需求修改起來都會得心應手,是以有必要了解透徹他們直接的關系與差別。

1,GNU

先看看wiki百科上的官方說明:

“GNU,名稱來自Gnu's Not Unix"的縮寫,一個類UNIX的作業系統,由GNU計劃推動,目标在于建立一個完全相容于UNIX的自由軟體環境。”

由于當時UNIX系統是商業軟體,是收費的,而且有一部分源碼是沒有開放的,是以在1983年,理查德·斯托曼提出GNU計劃,希望發展出一套完整的開放源代碼作業系統來取代Unix,計劃中的作業系統,名為GNU。

是以,GNU的出現的目的就是為了取代UNIX系統。

但是作業系統是包括很多軟體的,除了作業系統核心之外,還要有編輯器,編譯器,shell等等一些軟體來支援。

      1989年,GNU項目中的其他部份,如編輯器、編譯器、shell等都已經完成,獨缺作業系統核心。1990年,自由軟體基金會開始正式發展Hurd,作為GNU項目中的作業系統。

注意:linux并不是GNU計劃的一部分。linux隻是使用了許多GNU計劃軟體(包括GCC編譯器,文本編譯器等)。

      1991年,Linux出現,所有GNU項目中,運作于使用者空間的軟體,都可以在Linux上使用。許多開發者轉向于Linux,Linux成為常見的GNU計劃軟體運作平台。理查德·斯托曼主張,Linux作業系統使用了許多GNU計劃軟體,應正名為GNU/Linux,但沒有得到Linux社群的一緻認同,形成GNU/Linux命名争議。

1992年,Linux與其他GNU軟體結合,完全自由的作業系統正式誕生。許多程式員參與了Linux的開發與修改,也經常将Linux當成開發GNU計劃軟體的平台。該作業系統往往被稱為“GNU/Linux”或簡稱Linux。但Linux本身不屬于GNU計劃的一部份,GNU計劃自己的核心Hurd依然在開發中,但直到2013年為止,都還沒有穩定版本釋出。

GNU工程十幾年以來已經成為一個對軟體開發主要的影響力量,創造了無數的重要的工具,例如:強健的編譯器,有力的文本編輯器,甚至一個全功能的作業系統。這個工程是從1984年麻省理工學院的程式員理查德·斯托曼的想法得來的,他想要建立一個自由的、和UNIX類似的操作環境。從那時開始,許多程式員聚集起來開始開發一個自由的、高品質、易了解的軟體。

GNU計劃采用了部分當時已經可自由使用的軟體,例如TeX排版系統和X Window視窗系統等。不過GNU計劃也開發了大批其他的自由軟體,這些軟體也被移植到其他作業系統平台上,例如Microsoft Windows、BSD家族、Solaris及Mac OS。

許多UNIX系統上也安裝了GNU軟體,因為GNU軟體的品質比之前UNIX的軟體還要好。

是以,GNU計劃中的許多軟體目前在所有的作業系統中都應用廣泛(Unix,mac,linux,windows,bsd...),最出名的就是GCC了

總結:

       GNU計劃本來是為了開發一個自由系統來取代UNIX的,但是由于開發的核心hurd一直不怎麼樣,這個系統至今都沒出穩定版本,然而GNU計劃中開發的其他一些自由軟體,比如GCC編譯器,卻非常的好,在移植到各大作業系統上一直廣泛使用至今。

注意一點:

     文中說的自由軟體,千萬别與免費軟體混淆了,自由是說你可以自由的使用,當然前提是獲得了源碼才能自由的使用。

比如,你在一個應用裡面使用了gcc計劃的軟體,你賣自己的應用多少錢你自己定。免費的軟體不一定是開源的。

2,GCC

先看看wiki百科上的官方說明:

“ GCC(GNU Compiler Collection,GNU編譯器套裝),是一套由GNU開發的程式設計語言編譯器。它是一套以GPL及LGPL許可證所釋出的自由軟體,也是GNU項目的關鍵部分,亦是自由的類Unix及蘋果電腦Mac OS X 作業系統的标準編譯器。GCC(特别是其中的C語言編譯器)也常被認為是跨平台編譯器的事實标準。

GCC原名為GNU C語言編譯器(GNU C Compiler),因為它原本隻能處理C語言。GCC很快地擴充,變得可處理C++。之後也變得可處理Fortran、Pascal、Objective-C、Java、Ada,以及Go與其他語言。

原本用C開發,後來因為LLVM、Clang的崛起,令GCC更快将開發語言轉換為C++。許多C的愛好者在對C++一知半解的情況下主觀認定C++的性能一定會輸給C,但是Taylor給出了不同的意見,并表明C++不但性能不輸給C,而且能設計出更好,更容易維護的程式 ”

由于GCC已成為GNU系統的官方編譯器(包括GNU/Linux家族),它也成為編譯與建立其他作業系統的主要編譯器,包括BSD家族、Mac OS X、NeXTSTEP與BeOS。

GCC通常是跨平台軟體的編譯器首選。有别于一般局限于特定系統與運作環境的編譯器,GCC在所有平台上都使用同一個前端處理程式,産生一樣的中介碼,是以此中介碼在各個其他平台上使用GCC編譯,有很大的機會可得到正确無誤的輸出程式。

總結:

mac之前的cocoa架構便是用GCC編譯的,是以ios與mac os都是預設使用的GCC編譯器(現在是clang與llvm,下面會有介紹)

android的系統層因為是linux核心,自然也是GCC編譯的,但是android的app因為是運作在Dalvik虛拟機,是以用的不是GCC。

windows的應用,大部分都是使用的vs系列的編譯器,畢竟是windows自家的編譯器,用到GCC的不多。

3,Clang

先看看wiki百科上的官方說明: http://zh.wikipedia.org/wiki/Clang

“ Clang 是一個C、C++、Objective-C和Objective-C++程式設計語言的編譯器前端。它采用了底層虛拟機(LLVM)作為其後端。

它的目标是提供一個GNU編譯器套裝(GCC)的替代品。 Clang項目包括Clang前端和Clang靜态分析器等。

這個軟體項目在2005年由蘋果電腦發起,是LLVM編譯器工具集的前端(front-end),目的是輸出代碼對應的抽象文法樹(Abstract Syntax Tree, AST),并将代碼編譯成LLVM Bitcode。接着在後端(back-end)使用LLVM編譯成平台相關的機器語言 。Clang支援C、C++、Objective C。

Clang本身性能優異,其生成的AST所耗用掉的記憶體僅僅是GCC的20%左右。FreeBSD 10将Clang/LLVM作為預設編譯器.

測試證明Clang編譯Objective-C代碼時速度為GCC的3倍,還能針對使用者發生的編譯錯誤準确地給出建議。

總結:

GCC目前作為跨平台編譯器來說它的相容性無異是最強的,相容最強肯定是以犧牲一定的性能為基礎的,蘋果為了提高性能,是以專門針對mac系統開發了專用的編譯器clang與llvm,clang用于編譯器前段,llvm用于後端。

3,LLVM

先看看wiki百科上的官方說明:http://zh.wikipedia.org/wiki/LLVM

“ LLVM,它是一個編譯器的基礎建設,以C++寫成。它是為了任意一種程式設計語言寫成的程式,利用虛拟技術,創造出編譯時期,鍊結時期,運作時期以及“閑置時期”的優化。

在Xcode4之後,蘋果将Xcode的預設編譯器變成了LLVM,為什麼呢?

LLVM曆史

    Apple(包括中後期的NeXT) 一直使用GCC作為官方的編譯器。GCC作為開源世界的編譯器标準一直做得不錯,但Apple對編譯工具會提出更高的要求。

    一方面,是Apple對Objective-C語言(甚至後來對C語言)新增很多特性,但GCC開發者并不買Apple的帳——不給實作,是以索性後來兩者分成兩條分支分别開發,這也造成Apple的編譯器版本遠落後于GCC的官方版本。另一方面,GCC的代碼耦合度太高,不好獨立,而且越是後期的版本,代碼品質越差,但Apple想做的很多功能(比如更好的IDE支援)需要子產品化的方式來調用GCC,但GCC一直不給做,從根本上限制了LLVM-GCC的開發。 是以,這種不和讓Apple一直在尋找一個高效的、子產品化的、協定更放松的開源替代品,于是Apple請來了編譯器高材生Chris Lattner, LLVM就這樣産生了。

Clang曆史

    Apple吸收Chris Lattner的目的要比改進GCC代碼優化宏大得多——GCC系統龐大而笨重,而Apple大量使用的Objective-C在GCC中優先級很低。此外GCC作為一個純粹的編譯系統,與IDE配合得很差。加之許可證方面的要求,Apple無法使用LLVM 繼續改進GCC的代碼品質。于是,Apple決定從零開始寫 C、C++、Objective-C語言的前端 Clang,完全替代掉GCC。

    正像名字所寫的那樣,Clang隻支援C,C++和Objective-C三種C家族語言。2007年開始開發,C編譯器最早完成,而由于Objective-C相對簡單,隻是C語言的一個簡單擴充,很多情況下甚至可以等價地改寫為C語言對Objective-C運作庫的函數調用,是以在2009年時,已經完全可以用于生産環境。C++的支援也熱火朝天地進行着。  

更詳細的原因:

Xcode編譯器介紹: http://www.cnblogs.com/ydhliphonedev/archive/2012/08/29/2661726.html

總結:

因為GCC的編譯器已經慢慢無法滿足蘋果的需求,是以,蘋果開發了Clang與LLVM來完全取代GCC,Xcode4之後,蘋果的預設編譯器已經是LLVM了。Clang作為編譯器前端,LLVM作為編譯器後端。

在Xcode6.0中檢視預設編譯器:

4,編譯器相關知識

問題:蘋果以clang作為編譯器前端,llvm作為編譯器後端,那麼編譯器的前後端到底是什麼東西呢?

     我們先回到一個常識性的問題,什麼是編譯器呢?簡單地說,編譯器可以看作是一個語言翻譯器。就像把中文翻譯成英語一樣,編譯器可以把進階語言翻譯成計算機能夠執行的機器語言。這樣看來,GCC可以算得上是一個精通多國語言的進階翻譯官了。

最簡單的GCC使用指令如下所示:

    gcc  hello.c  -o  hello

GCC接受hello.c作為輸入,最後産生目标可執行代碼hello。這個簡單的流程實際上經曆了很多步驟,如下圖所示:

雖然我們隻用了一條指令就完成了編譯,但實際上gcc指令依次呼叫了cpp,gcc自己,gas以及ld來進行完整的編譯流程,最後生成最終的可執行檔案hello。

學過編譯原理這門課程的同學對下面這副圖應該很熟悉,這是經典的編譯流程。

下面以GCC編譯器為例,GCC作為經典的編譯器,自然也是遵循這個教科書流程(實際GCC的處理更複雜點,但本質上是一樣的)。我們先簡化一下上面這幅圖,以中間代碼為分界,前面的詞法分析、文法分析、語義分析我們把它稱之為前端處理,後面的優化和目标代碼生成我們稱之為後端處理。

試想一下,是否可以為不同的進階語言單獨寫一個前端,然後為不同的處理器架構單獨寫一個後端呢?

GCC基本上也是這麼實作的,不過不要誤會,并沒有一個統一的gcc執行程式能夠處理如此多的前端和後端,每個語言的編譯器都是一個獨立的程式(如C語言的編譯器是gcc,C++的編譯器是g++),而不同的後端也要對應不同的可執行程式。你可以下載下傳單獨的一份GCC源代碼,通過不同的configure來生成自己需要的編譯器。

而且,編譯器的實作也比上圖要複雜的多,前端的主要功能是産生一個可供後端處理的文法樹,而文法樹結構實際上很難與處理器架構脫鈎,這些都是編譯器應用中需要解決的問題。

GCC強大的真正原因是什麼?是因為它支援了衆多的前端和後端嗎?這些都不過是一個表象而已。GCC是一款真正自由的編譯器,我們可以随時把代碼拿過來修改以實作自己需要的功能。如果你的硬體平台增加了一些指令,而普通的編譯器并不能産生這些指令怎麼辦?在GCC後端添加這些指令吧。如果你覺得C語言用的不太順手,想給它添加一些功能怎麼辦?修改GCC的前端吧。因為有了GCC,我們才擁有這些自由,以及迅速實作自己想法的能力,而這些才是GCC強大背後的基礎。

更詳細的關于GCC:http://blog.csdn.net/itianyi/article/details/43054199