Linux【学习心得】深入剖析软件的源码安装
轉(zhuǎn)自:http://www.imooc.com/wenda/detail/242044
? ? 學(xué)習(xí)了一段時(shí)間的Linux,相信大家都會(huì)遇到需要安裝軟件的情況,而新手(比如我)對(duì)于這個(gè)問(wèn)題肯定是特別頭疼。照著網(wǎng)上的步驟裝,可能出現(xiàn)莫名其妙的 錯(cuò)誤,不知道如何是好。更關(guān)鍵的是不知道每一步都是在干嘛,所以即使我們依葫蘆畫瓢地裝了多次某個(gè)軟件,遇到問(wèn)題也沒(méi)有辦法解決。那今天我就來(lái)談?wù)?Linux上源碼安裝軟件的一些東西,我也是新手,勿噴……
????首先我們應(yīng)該知道,計(jì)算機(jī)能夠識(shí)別的只有二進(jìn)制,也就是010101這樣的串,或者說(shuō)是高低電平……
????那么我們平時(shí)敲的代碼,比如說(shuō)C語(yǔ)言打印一個(gè)"Hello world",相信大家都無(wú)比熟悉吧。
| #include<stdio.h>int?main(){???printf("Hello?world!");???return?0;} |
我 們把上面的文件保存為hello.c。對(duì)于計(jì)算機(jī)來(lái)說(shuō)這只是一個(gè)文本文件,里面存的這些英文字母和符號(hào)它是看不懂的,對(duì)它來(lái)說(shuō)就像天書一樣不知所云。那我 們要讓這段代碼可以執(zhí)行,就必須讓計(jì)算機(jī)能看懂它。比如我們可以把這段代碼用匯編語(yǔ)言寫一遍,雖然更貼近底層,但計(jì)算機(jī)依然看不懂,我們還是得把它寫成機(jī) 器碼才行。
WTF!這我哪兒會(huì)啊!!不用擔(dān)心,我們不會(huì),但是有大牛會(huì),而且他們已經(jīng)做得非常棒了,那就是大名鼎鼎的gcc。
gcc就是我們常說(shuō)的編譯器(事實(shí)上這只是它的一小部分功能),它能把我們?nèi)四芸炊腃語(yǔ)言代碼翻譯成機(jī)器能夠看懂的二進(jìn)制代碼。這樣這段代碼就能在計(jì)算機(jī)上愉快地運(yùn)行了。
那我們現(xiàn)在用gcc來(lái)編譯一下hello.c
| gcc?hello.c |
執(zhí)行后我們來(lái)看看
可以發(fā)現(xiàn)新生成了一個(gè)可執(zhí)行文件a.out
我們可以運(yùn)行一下它試試
| ./a.out |
可以看到成功地輸出了"Hello world!"也就是說(shuō)gcc把我們的C語(yǔ)言文件成功翻譯成了計(jì)算機(jī)能夠識(shí)別并運(yùn)行的二進(jìn)制文件。
到這里大家可能會(huì)比較疑惑,你講安裝軟件,講編譯C語(yǔ)言代碼干什么。我只想說(shuō),你先別著急,這是為后面理解安裝過(guò)程做鋪墊,是非常重要的,理解軟件安裝的那些步驟在干什么可全看這些了。
上面我們用gcc編譯好了一個(gè)c文件,雖然就是一條指令,但是其實(shí)gcc干了很多事情,我們可以把它分為4步:預(yù)處理、翻譯成匯編語(yǔ)言、匯編、鏈接。我們可以這么來(lái)看看
首先刪除掉剛剛生成的a.out
| rm?-rf?a.out |
然后我們執(zhí)行下面這條指令
| gcc?-E?hello.c?-o?hello.i |
誒,我們可以看到,生成了一個(gè)hello.i文件,我們打開(kāi)它看看可以發(fā)現(xiàn),其實(shí)這個(gè)hello.i就是把#include<stdio.h>的stdio.h文件寫了進(jìn)來(lái)。
然后我們?cè)賵?zhí)行
| gcc?-S?hello.i?-o?hello.s |
那么可以看到我們生成了一個(gè)hello.s文件,打開(kāi)它看看
其實(shí)就是把上一步的hello.i翻譯成了匯編語(yǔ)言
接著我們運(yùn)行
| gcc?-c?hello.s?-o?hello.o |
生成了一個(gè)hello.o文件,當(dāng)我們想查看這個(gè)文件時(shí)系統(tǒng)會(huì)提示說(shuō)這是個(gè)二進(jìn)制文件。
當(dāng)然這個(gè)文件依然是不能執(zhí)行的,我們可以用file命令看看,它是沒(méi)有excutable屬性的。我們還缺少最后一步
| gcc?hello.o?-o?hello.exe |
最后就生成了hello.exe這個(gè)可執(zhí)行文件。在這里我還是想說(shuō)一下,linux不是靠后綴來(lái)區(qū)分文件的,后綴只是給人看的。.exe是windows里的可執(zhí)行文件的后綴,但我們不應(yīng)該帶入太多windows里的東西到linux,所以我其實(shí)不推薦給可執(zhí)行文件加.exe后綴。
當(dāng)然我這里只是方便大家看,所以執(zhí)行
| ./hello.exe |
就可以打印出"Hello world!"了
到這里大家應(yīng)該也看明白了編譯一個(gè)C語(yǔ)言文件的整個(gè)過(guò)程了,但是細(xì)心的同學(xué)可能就會(huì)有疑問(wèn)了:既然hello.o是個(gè)二進(jìn)制文件我們也看不懂,gcc干嘛生成它,為什么不直接從hello.s生成hello.exe?
這真的是一個(gè)好問(wèn)題,也是后面講Linux下源碼安裝軟件非常核心的地方。那我們就來(lái)講講這個(gè).o是啥東東
其實(shí)在我們實(shí)際的工程項(xiàng)目中,一個(gè)項(xiàng)目是有很多個(gè)c文件的,這些文件會(huì)互相調(diào)用。比如看這個(gè)例子
我要輸出一個(gè)"Hello world!"但是我想把輸出單獨(dú)寫成一個(gè)output.c文件供其它文件調(diào)用。
先看output.c
| #include<stdio.h>#include?"haha.h"void?output(){????printf("Hello?world!");} |
然后是主程序hello.c
| #include<stdio.h>#include?"haha.h"int?main(){???output();???return?0;} |
然后是haha.h
| void?output(); |
以上都是C語(yǔ)言需要關(guān)心的地方,大家如果這里看不明白不要緊,關(guān)鍵看我之后的操作
首先我們來(lái)分別編譯兩個(gè).c文件為.o
| gcc?-c?hello.c?-o?hello.ogcc?-c?output.c?-o?output.o |
完了之后呢,我們進(jìn)行一次鏈接
| gcc?hello.o?output.o?-o?final |
這樣我們就得到了一個(gè)可執(zhí)行文件final
上面的內(nèi)容大家只需要關(guān)心最后一句,也就是?
gcc hello.o output.o -o final
hello.o和output.o是兩個(gè)獨(dú)立的文件,但是hello會(huì)用到output的功能,所以我們把它鏈接起來(lái),最后生成了一個(gè)可執(zhí)行文件,執(zhí)行就能輸出"Hello world!"啦!。那上面代碼沒(méi)有輸出換行所以看著有點(diǎn)別扭,我用箭頭標(biāo)出來(lái)了。
那這么做有什么好處呢?想象一下,我們?nèi)绻薷哪硞€(gè)文件,其它文件沒(méi)有改變的話,只需要重新編譯那一個(gè)文件,再鏈接即可,而不需要重新編譯所有的文件。不知道大家裝過(guò)mysql沒(méi)有,編譯一次要30分鐘,要是想做個(gè)小小的修改,每次重新編譯那得多么痛苦……
至于怎么鏈接之類的問(wèn)題不在我們的討論范疇,有興趣大家可以上google百度一下。
那 回到的主題,我們要安裝一個(gè)軟件,都會(huì)先去下載一個(gè)"安裝包"。既然是"包"那肯定是有很多源文件的,比如我們的apache,里面有很多c源程序,每個(gè) c程序都實(shí)現(xiàn)了不同的功能。所以我們?nèi)绻惭bapache(即生成一個(gè)可執(zhí)行文件),一定是先各種編譯,最后把各種.o文件鏈接成一個(gè)可執(zhí)行文件。那么 問(wèn)題來(lái)了,幾十上百個(gè).c文件我要自己編譯再鏈接豈不是瘋了?對(duì),確實(shí)會(huì)瘋掉的!你可能都不知道你編譯了哪些沒(méi)有編譯哪些……
所以接下來(lái)就會(huì)介紹大家可能非常熟悉make。這個(gè)玩意兒相信在linux上源碼安裝過(guò)軟件的同學(xué)都知道而且用過(guò)而且?guī)缀趺總€(gè)軟件安裝都會(huì)用到。它到底是用到干什么的呢?其實(shí)啊,它就是來(lái)幫我們解決以上問(wèn)題的,讓我們的編譯鏈接更加方便,讓世界更加美好。
那為了說(shuō)明問(wèn)題,我們?cè)倏匆粋€(gè)例子
我們的代碼可能會(huì)調(diào)用系統(tǒng)的已經(jīng)實(shí)現(xiàn)過(guò)的函數(shù),這時(shí)候編譯會(huì)發(fā)生神馬呢?
sin.c
| #include<stdio.h>int?main(){????double?v;????v?=?sin?(3.14?/?6);??//???pi/6????return?0;} |
這個(gè)sin我們是沒(méi)有實(shí)現(xiàn)的而是去調(diào)用系統(tǒng)內(nèi)的sin
那 如果我們直接編譯肯定會(huì)報(bào)'未聲明的函數(shù)調(diào)用',這個(gè)大家都知道,所以我們應(yīng)該怎么做呢?既然我們要調(diào)用系統(tǒng)已經(jīng)實(shí)現(xiàn)好的sin,那么我們得知道它在哪 兒?在linux中呢,libm.so里面實(shí)現(xiàn)了sin,所以我們需要在編譯命令中加入這個(gè)路徑,也就是告訴編譯器:“你要是發(fā)現(xiàn)未定義的函數(shù),就去這個(gè) 路徑里找找”。
所以我們來(lái)看看這個(gè)libm.so到底在哪兒
| locate?libm.so |
然后我們編譯時(shí)加入這個(gè)path
| gcc?sin.c?-lm?-L/usr/lib64 |
-l是說(shuō)要增加library
-m是說(shuō)尋找名字叫做libm.so的東西,lib是大多數(shù)庫(kù)文件的前綴所以我們省掉了。
-L+path就是說(shuō)讓gcc到這個(gè)path下面來(lái)找
這里會(huì)爆出一個(gè)warning,但是沒(méi)關(guān)系,只要不是error就好,可以看到已經(jīng)生成了我們想要的a.out
執(zhí)行它,就得到了我要的滑板鞋,不對(duì),這都是哪跟哪兒啊……就得到了我要的0.5
所以其實(shí)說(shuō)到這里,大家應(yīng)該都知道一個(gè)軟件從源碼到可執(zhí)行文件應(yīng)該怎么安裝了。要是你閑的蛋疼,可以嘗試一下用gcc手動(dòng)安裝mysql,不過(guò)我祝你幸?!?/p>
說(shuō)了這么多其實(shí)我都在為make做鋪墊,可以想象啊,一個(gè)軟件包里的源文件,可能會(huì)調(diào)用各種系統(tǒng)的庫(kù)函數(shù),也會(huì)有相互的依賴關(guān)系,那么我們手動(dòng)編譯起來(lái)就會(huì)特別麻煩。make就是來(lái)簡(jiǎn)化以上操作的。
make具體干了些神馬呢?
首先,make會(huì)在當(dāng)前目錄下尋找一個(gè)叫做Makefile的文件,比如我們有如下的源文件
然后我們新建一個(gè)Makefile,編輯它
注意,命令行(2,3行)必須以tab開(kāi)頭
接下來(lái)執(zhí)行make
可以看到整個(gè)過(guò)程一氣呵成啊。
所以你知道m(xù)ake的方便了吧,一條指令就搞定了所有。
但是又有同學(xué)問(wèn)了,我寫shell腳本不也能做到嗎?確實(shí)能做到,但make還有個(gè)強(qiáng)大的功能——diff,用過(guò)git的同學(xué)都知道,diff用來(lái)判斷修改過(guò)的文件,那么make只會(huì)去重新編譯修改過(guò)的部分,這會(huì)節(jié)約很多時(shí)間。
那 又有好奇的同學(xué)要問(wèn)了,這個(gè)Makefile還不是得寫,我寫一遍Makefile還是得花好長(zhǎng)時(shí)間啊!這個(gè)不用咱們擔(dān)心,這是軟件提供者需要干的。但是 軟件提供者也不會(huì)直接給我們寫Makefile,想一想原因也很簡(jiǎn)答。例如上面的-L/usr/lib64,libm.so在我的電腦里在這個(gè)路徑中,但 是其它的可能不這樣,要是Makefile寫死了不就完蛋了嗎?
所以就有了./configure。這是個(gè)檢測(cè)腳本,用來(lái)檢測(cè)咱們的系統(tǒng)有 沒(méi)有安裝軟件需要的庫(kù)函數(shù)(某個(gè)需要的庫(kù)函數(shù)都會(huì)去默認(rèn)的路徑下找),要是缺少某些庫(kù)函數(shù),那么軟件安裝就不能成功。所以啊,大家可能都能理解 了./configure里有時(shí)候會(huì)加上 --xxx=/usr/local是什么意思了吧(xxx庫(kù)或者依賴包去/usr/local里去找),那么如果./configure提示我們?nèi)鄙倌承?依賴,大家就知道該怎么辦了嗎?當(dāng)然是缺哪個(gè)就locate一下那個(gè)文件的路徑然后在./configure的命令中加上路徑作為參數(shù)咯。那要是 locate沒(méi)有需要的依賴,再自己去網(wǎng)上下載并安裝,這又是一個(gè)相同的過(guò)程(有木有遞歸的感覺(jué))
那么如果./configure成功了, 我們就可以用make來(lái)編譯和鏈接了。有同學(xué)又要問(wèn)了,你說(shuō)了./configure,但是make是需要Makefile的呀!不要急,. /configure這個(gè)檢測(cè)腳本如果檢測(cè)成功了,就會(huì)自動(dòng)生成Makefile,至于怎么生成,生成內(nèi)容是什么,這是軟件開(kāi)發(fā)者的事兒,那你要是有興趣 可以打開(kāi)看看。
所以接下來(lái)我們執(zhí)行make,然后就會(huì)看到一溜的刷屏,這其實(shí)就是make在幫咱們挨個(gè)編譯源文件然后鏈接它們。
make 結(jié)束以后呢我們可以執(zhí)行make install,make install會(huì)在Makefile里找對(duì)應(yīng)的參數(shù),然后把make成功的可執(zhí)行文件放到Makefile指定的路徑。如果我們不make install,那么生成的可執(zhí)行文件就依然還在我們當(dāng)前目錄下。
這便是源碼安裝軟件的整個(gè)過(guò)程了。
所以總結(jié)一下,其實(shí)最重要的一步就是./configure和./configure出錯(cuò)了怎么解決。大家理解了之后可以試著去源碼安裝一下LNMP,幫助加深印象。希望本文對(duì)大家有所幫助,3Q~
轉(zhuǎn)載于:https://blog.51cto.com/8718813/1619042
總結(jié)
以上是生活随笔為你收集整理的Linux【学习心得】深入剖析软件的源码安装的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【python 图片识别】python识
- 下一篇: 嵌入式linux添加字体,嵌入式字体编辑