溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

linux編譯安裝的過程是什么

發(fā)布時(shí)間:2023-02-14 13:58:25 來源:億速云 閱讀:148 作者:iii 欄目:建站服務(wù)器

這篇文章主要介紹“l(fā)inux編譯安裝的過程是什么”,在日常操作中,相信很多人在linux編譯安裝的過程是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”linux編譯安裝的過程是什么”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

在linux中,編譯安裝是指將源代碼根據(jù)機(jī)器自身的硬件、內(nèi)核、環(huán)境變?yōu)闄C(jī)器可執(zhí)行的代碼文件,然后將可執(zhí)行文件安裝到操作系統(tǒng)里。因?yàn)槭轻槍?duì)本機(jī)軟硬件環(huán)境編譯的,生成的二進(jìn)制程序運(yùn)行起來理論上性能更好,更節(jié)省資源。

什么是編譯安裝

  • 編譯:將源代碼變?yōu)闄C(jī)器可執(zhí)行的代碼文件。

  • 安裝:將可執(zhí)行文件安裝到操作系統(tǒng)里,才可以使用。

編譯安裝,就是使用源代碼,根據(jù)機(jī)器自身的硬件、內(nèi)核、環(huán)境進(jìn)行編譯,生成二進(jìn)制文件,優(yōu)點(diǎn)是不管什么機(jī)器,只要有完整的編譯環(huán)境(基本上所有的Linux發(fā)行版都有自己的一套完整的編譯環(huán)境),就可以生成適合自己機(jī)器的二進(jìn)制包,同時(shí)因?yàn)槭轻槍?duì)本機(jī)軟硬件環(huán)境編譯的,生成的二進(jìn)制程序運(yùn)行起來理論上性能更好,更節(jié)省資源。

  • 缺點(diǎn):是對(duì)新手來說編譯過程比較麻煩(當(dāng)然如果你熟悉了其實(shí)也很快),同時(shí)升級(jí)比較麻煩(當(dāng)然有些程序編譯安裝過程會(huì)自己解決升級(jí)沖突和覆蓋)

說明:

源碼要運(yùn)行,必須先轉(zhuǎn)成二進(jìn)制的機(jī)器碼。這是編譯器的任務(wù)。

比如,下面這段源碼(假定文件名叫做test.c)。

#include <stdio.h>

int main(void)
{
  fputs("Hello, world!\n", stdout);
  return 0;
}

要先用編譯器處理一下,才能運(yùn)行。

$ gcc test.c
$ ./a.out
Hello, world!

對(duì)于復(fù)雜的項(xiàng)目,編譯過程還必須分成三步。

$ ./configure
$ make  
$ make install

編譯過程流程圖:

linux編譯安裝的過程是什么

編譯的具體過程

1. 配置(configure)

編譯器在開始工作之前,需要知道當(dāng)前的系統(tǒng)環(huán)境,比如標(biāo)準(zhǔn)庫(kù)在哪里、軟件的安裝位置在哪里、需要安裝哪些組件等等。這是因?yàn)椴煌?jì)算機(jī)的系統(tǒng)環(huán)境不一樣,通過指定編譯參數(shù),編譯器就可以靈活適應(yīng)環(huán)境,編譯出各種環(huán)境都能運(yùn)行的機(jī)器碼。這個(gè)確定編譯參數(shù)的步驟,就叫做"配置"(configure)。

這些配置信息保存在一個(gè)配置文件之中,約定俗成是一個(gè)叫做configure的腳本文件。通常它是由autoconf工具生成的。編譯器通過運(yùn)行這個(gè)腳本,獲知編譯參數(shù)。

configure腳本已經(jīng)盡量考慮到不同系統(tǒng)的差異,并且對(duì)各種編譯參數(shù)給出了默認(rèn)值。如果用戶的系統(tǒng)環(huán)境比較特別,或者有一些特定的需求,就需要手動(dòng)向configure腳本提供編譯參數(shù)。

$ ./configure --prefix=/www --with-mysql

上面代碼是php源碼的一種編譯配置,用戶指定安裝后的文件保存在www目錄,并且編譯時(shí)加入mysql模塊的支持。

2. 確定標(biāo)準(zhǔn)庫(kù)和頭文件的位置

源碼肯定會(huì)用到標(biāo)準(zhǔn)庫(kù)函數(shù)(standard library)和頭文件(header)。它們可以存放在系統(tǒng)的任意目錄中,編譯器實(shí)際上沒辦法自動(dòng)檢測(cè)它們的位置,只有通過配置文件才能知道。

編譯的第二步,就是從配置文件中知道標(biāo)準(zhǔn)庫(kù)和頭文件的位置。一般來說,配置文件會(huì)給出一個(gè)清單,列出幾個(gè)具體的目錄。等到編譯時(shí),編譯器就按順序到這幾個(gè)目錄中,尋找目標(biāo)。

3. 確定依賴關(guān)系

對(duì)于大型項(xiàng)目來說,源碼文件之間往往存在依賴關(guān)系,編譯器需要確定編譯的先后順序。假定A文件依賴于B文件,編譯器應(yīng)該保證做到下面兩點(diǎn)。

(1)只有在B文件編譯完成后,才開始編譯A文件。

(2)當(dāng)B文件發(fā)生變化時(shí),A文件會(huì)被重新編譯。

編譯順序保存在一個(gè)叫做makefile的文件中,里面列出哪個(gè)文件先編譯,哪個(gè)文件后編譯。而makefile文件由configure腳本運(yùn)行生成,這就是為什么編譯時(shí)configure必須首先運(yùn)行的原因。

在確定依賴關(guān)系的同時(shí),編譯器也確定了,編譯時(shí)會(huì)用到哪些頭文件。

4. 頭文件的預(yù)編譯(precompilation)

不同的源碼文件,可能引用同一個(gè)頭文件(比如stdio.h)。編譯的時(shí)候,頭文件也必須一起編譯。為了節(jié)省時(shí)間,編譯器會(huì)在編譯源碼之前,先編譯頭文件。這保證了頭文件只需編譯一次,不必每次用到的時(shí)候,都重新編譯了。

不過,并不是頭文件的所有內(nèi)容,都會(huì)被預(yù)編譯。用來聲明宏的#define命令,就不會(huì)被預(yù)編譯。

5. 預(yù)處理(Preprocessing)

預(yù)編譯完成后,編譯器就開始替換掉源碼中bash的頭文件和宏。以本文開頭的那段源碼為例,它包含頭文件stdio.h,替換后的樣子如下。

extern int fputs(const char *, FILE *);
extern FILE *stdout;

int main(void)
{
    fputs("Hello, world!\n", stdout);
    return 0;
}

為了便于閱讀,上面代碼只截取了頭文件中與源碼相關(guān)的那部分,即fputs和FILE的聲明,省略了stdio.h的其他部分(因?yàn)樗鼈兎浅iL(zhǎng))。另外,上面代碼的頭文件沒有經(jīng)過預(yù)編譯,而實(shí)際上,插入源碼的是預(yù)編譯后的結(jié)果。編譯器在這一步還會(huì)移除注釋。

這一步稱為"預(yù)處理"(Preprocessing),因?yàn)橥瓿芍?,就要開始真正的處理了。

6. 編譯(Compilation)

預(yù)處理之后,編譯器就開始生成機(jī)器碼。對(duì)于某些編譯器來說,還存在一個(gè)中間步驟,會(huì)先把源碼轉(zhuǎn)為匯編碼(assembly),然后再把匯編碼轉(zhuǎn)為機(jī)器碼。

下面是本文開頭的那段源碼轉(zhuǎn)成的匯編碼。

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "Hello, world!\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    stdout(%rip), %rax
    movq    %rax, %rcx
    movl    $14, %edx
    movl    $1, %esi
    movl    $.LC0, %edi
    call    fwrite
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 4.9.1-19) 4.9.1"
    .section    .note.GNU-stack,"",@progbits

這種轉(zhuǎn)碼后的文件稱為對(duì)象文件(object file)。

注:make (gcc), 其調(diào)用 gcc 執(zhí)行編譯的過程依賴于配置文件makefile

7. 連接(Linking)

對(duì)象文件還不能運(yùn)行,必須進(jìn)一步轉(zhuǎn)成執(zhí)行文件。如果你仔細(xì)看上一步的轉(zhuǎn)碼結(jié)果,會(huì)發(fā)現(xiàn)其中引用了stdout函數(shù)和fwrite函數(shù)。也就是說,程序要正常運(yùn)行,除了上面的代碼以外,還必須有stdout和fwrite這兩個(gè)函數(shù)的代碼,它們是由C語言的標(biāo)準(zhǔn)庫(kù)提供的。

編譯器的下一步工作,就是把外部函數(shù)的代碼(通常是后綴名為.lib和.a的文件),添加到可執(zhí)行文件中。這就叫做連接(linking)。這種通過拷貝,將外部函數(shù)庫(kù)添加到可執(zhí)行文件的方式,叫做靜態(tài)連接(static linking),后文會(huì)提到還有動(dòng)態(tài)連接(dynamic linking)。

make命令的作用,就是從第四步頭文件預(yù)編譯開始,一直到做完這一步。

8. 安裝(Installation)

上一步的連接是在內(nèi)存中進(jìn)行的,即編譯器在內(nèi)存中生成了可執(zhí)行文件。下一步,必須將可執(zhí)行文件保存到用戶事先指定的安裝目錄。

表面上,這一步很簡(jiǎn)單,就是將可執(zhí)行文件(連帶相關(guān)的數(shù)據(jù)文件)拷貝過去就行了。但是實(shí)際上,這一步還必須完成創(chuàng)建目錄、保存文件、設(shè)置權(quán)限等步驟。這整個(gè)的保存過程就稱為"安裝"(Installation)。

9. 操作系統(tǒng)連接

可執(zhí)行文件安裝后,必須以某種方式通知操作系統(tǒng),讓其知道可以使用這個(gè)程序了。比如,我們安裝了一個(gè)文本閱讀程序,往往希望雙擊txt文件,該程序就會(huì)自動(dòng)運(yùn)行。

這就要求在操作系統(tǒng)中,登記這個(gè)程序的元數(shù)據(jù):文件名、文件描述、關(guān)聯(lián)后綴名等等。Linux系統(tǒng)中,這些信息通常保存在/usr/share/applications目錄下的.desktop文件中。另外,在Windows操作系統(tǒng)中,還需要在Start啟動(dòng)菜單中,建立一個(gè)快捷方式。

這些事情就叫做"操作系統(tǒng)連接"。make install命令,就用來完成"安裝"和"操作系統(tǒng)連接"這兩步。

10. 生成安裝包

寫到這里,源碼編譯的整個(gè)過程就基本完成了。但是只有很少一部分用戶,愿意耐著性子,從頭到尾做一遍這個(gè)過程。事實(shí)上,如果你只有源碼可以交給用戶,他們會(huì)認(rèn)定你是一個(gè)不友好的家伙。大部分用戶要的是一個(gè)二進(jìn)制的可執(zhí)行程序,立刻就能運(yùn)行。這就要求開發(fā)者,將上一步生成的可執(zhí)行文件,做成可以分發(fā)的安裝包。

所以,編譯器還必須有生成安裝包的功能。通常是將可執(zhí)行文件(連帶相關(guān)的數(shù)據(jù)文件),以某種目錄結(jié)構(gòu),保存成壓縮文件包,交給用戶。

11. 動(dòng)態(tài)連接(Dynamic linking)

正常情況下,到這一步,程序已經(jīng)可以運(yùn)行了。至于運(yùn)行期間(runtime)發(fā)生的事情,與編譯器一概無關(guān)。但是,開發(fā)者可以在編譯階段選擇可執(zhí)行文件連接外部函數(shù)庫(kù)的方式,到底是靜態(tài)連接(編譯時(shí)連接),還是動(dòng)態(tài)連接(運(yùn)行時(shí)連接)。所以,最后還要提一下,什么叫做動(dòng)態(tài)連接。

前面已經(jīng)說過,靜態(tài)連接就是把外部函數(shù)庫(kù),拷貝到可執(zhí)行文件中。這樣做的好處是,適用范圍比較廣,不用擔(dān)心用戶機(jī)器缺少某個(gè)庫(kù)文件;缺點(diǎn)是安裝包會(huì)比較大,而且多個(gè)應(yīng)用程序之間,無法共享庫(kù)文件。動(dòng)態(tài)連接的做法正好相反,外部函數(shù)庫(kù)不進(jìn)入安裝包,只在運(yùn)行時(shí)動(dòng)態(tài)引用。好處是安裝包會(huì)比較小,多個(gè)應(yīng)用程序可以共享庫(kù)文件;缺點(diǎn)是用戶必須事先安裝好庫(kù)文件,而且版本和安裝位置都必須符合要求,否則就不能正常運(yùn)行。

現(xiàn)實(shí)中,大部分軟件采用動(dòng)態(tài)連接,共享庫(kù)文件。這種動(dòng)態(tài)共享的庫(kù)文件,Linux平臺(tái)是后綴名為.so的文件,Windows平臺(tái)是.dll文件,Mac平臺(tái)是.dylib文件。

Linux編譯安裝的具體實(shí)現(xiàn)

1.編譯安裝源程序的前提:

1).提供開發(fā)環(huán)境:開發(fā)工具和開發(fā)庫(kù)

2).編譯安裝需要的包組:

Development Tools、Server Platform Development、Desktop Platform Development、Debug Tools

2.configure腳本常用的選項(xiàng):

--help獲取./configure腳本幫助
--prefix=: 指定安裝路徑;多數(shù)程序都有默認(rèn)安裝路徑;
--sysconfidr=: 指定配置文件安裝路徑;
--with-PACKAGE[=ARG]:在自由軟件社區(qū)里,有使用已有軟件包和庫(kù)的優(yōu)秀傳統(tǒng).當(dāng)用'configure'來配置一個(gè)源碼樹時(shí),
可以提供其他已經(jīng)安裝的軟件包的信息
--without-PACKAGE:有時(shí)候你可能不想讓你的軟件包與系統(tǒng)已有的軟件包交互。例如,你可能不想讓你的新編譯器使用
GNU ld
--enable-FEATURE:一些軟件包可能提供了一些默認(rèn)被禁止的特性,可以使用'--enable-FEATURE'來起用它
--disable-EEATURE:關(guān)閉指定的默認(rèn)特性

3.編譯安裝源程序方法:

1)展開源代碼,找INSTALL、README;不存在此類文件時(shí),找項(xiàng)目官方文檔;

2)根據(jù)安裝說明執(zhí)行安裝操作;

4.程序安裝于專用目錄時(shí),安裝后的配置:

1)、導(dǎo)出二進(jìn)制程序所在路徑至PATH環(huán)境中

# export PATH=/usr/local/nginx/sbin:$PATH

實(shí)現(xiàn)永久有效的辦法:
                /etc/profile.d/*.sh

2)導(dǎo)出庫(kù)文件給OS

OS查找?guī)煳募椒ǎ焊鶕?jù)/etc/ld.so.conf配置文件指定的路徑搜索,或搜索/lib, /lib64, /usr/lib, /usr/lib64,把查找到的所有的庫(kù)文件路徑和其名稱映射關(guān)系保存為一個(gè)緩存文件/etc/ld.so.cache;

/etc/ld.so.conf配置文件有其它組成部分:/etc/ld.so.conf.d/*.conf

假設(shè)nginx安裝于/usr/local/nginx,此目錄中有其庫(kù)文件子目錄lib,導(dǎo)出此目錄中庫(kù)文件:

(1)新建文件/etc/ld.so.conf.d/nginx.conf,在文件添加如下行:

/usr/local/nginx/lib

(2)運(yùn)行命令:ldconfig

ldconfig的主要用途:

默認(rèn)搜尋/lilb和/usr/lib,以及配置文件/etc/ld.so.conf內(nèi)所列的目錄下的庫(kù)文件。

搜索出可共享的動(dòng)態(tài)鏈接庫(kù),庫(kù)文件的格式為:lib***.so.**,進(jìn)而創(chuàng)建出動(dòng)態(tài)裝入程序(ld.so)所需的連接和緩存文件。

緩存文件默認(rèn)為/etc/ld.so.cache,該文件保存已排好序的動(dòng)態(tài)鏈接庫(kù)名字列表。

ldconfig通常在系統(tǒng)啟動(dòng)時(shí)運(yùn)行,而當(dāng)用戶安裝了一個(gè)新的動(dòng)態(tài)鏈接庫(kù)時(shí),就需要手工運(yùn)行這個(gè)命令。

常用選項(xiàng):

-v: 用此選項(xiàng)時(shí),ldconfig將顯示正在掃描的目錄及搜索到的動(dòng)態(tài)鏈接庫(kù),還有它所創(chuàng)建的連接的名字.
-p: 顯示當(dāng)前OS已經(jīng)加載到的所有庫(kù)文件名稱及其文件所在路徑的映射關(guān)系;

ldconfig需要注意的地方:

(a)往/lib和/usr/lib里面加?xùn)|西,是不用修改/etc/ld.so.conf文件的,但是添加完后需要調(diào)用下ldconfig,不然添加的library會(huì)找不到。

(b)如果添加的library不在/lib和/usr/lib里面的話,就一定要修改/etc/ld.so.conf文件,往該文件追加library所在的路徑,然后也需要重新調(diào)用下ldconfig命令。比如在安裝mysql的時(shí)候,其庫(kù)文件/usr/local/mysql/lib,就需要追加到/etc/ld.so.conf文件中。命令如下:

# echo "/usr/local/mysql/lib" >> /etc/ld.so.conf

# ldconfig -v | grep mysql

(c)如果添加的library不在/lib或/usr/lib下,但是卻沒有權(quán)限操作寫/etc/ld.so.conf文件的話,這時(shí)就需要往export里寫一個(gè)全局變量LD_LIBRARY_PATH,就可以了。

(3)幫助文件導(dǎo)出

man命令搜索特定路徑查找手冊(cè)頁文件,這些路徑是定義在/etc/man.config中的MANPATH參數(shù)所指定的路徑下的;

新增辦法:編輯/etc/man.config文件,新增一個(gè)MANPATH參數(shù),其值為新安裝程序的man手冊(cè)所在的目錄;

            /usr/local/nginx/share/man/{man1,man8}

            man -M /path/to/man KEYWORD

(4)頭文件導(dǎo)出

有些程序安裝后會(huì)生成對(duì)自己擁有庫(kù)文件調(diào)用接口相關(guān)頭文件系統(tǒng)查找頭文件的路徑為/usr/include

導(dǎo)出獨(dú)立安裝應(yīng)用程序的頭文件方法:創(chuàng)建鏈接至/usr/include下即可;

例如:

/usr/local/nginx/include
# ln -sv /usr/local/nginx/include/* /usr/include/
# ln -sv /usr/local/nginx/include /usr/include/nginx

perl源程序的編譯安裝方法:

    (1) perl Makefile.in
    (2) make
    (3) make install

到此,關(guān)于“l(fā)inux編譯安裝的過程是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI