linux應用之make命令詳解

從源代碼安裝過軟件的朋友必定對 ./configure && make && make install 安裝三步曲很是熟悉了。然而究竟這個過程當中的每一步幕後都發生了些什麼呢?今天小編將帶你一探究竟。

 

深刻理解這個過程將有助於你在LFS的基礎上玩出本身的花樣來。不過須要說明的是這裏對 Makefile 和 make 的講解是至關近視和粗淺的,可是對於理解安裝過程來講足夠了。

 

概述編程

 

用一句話來解釋這個過程就是:根據源碼包中 Makefile.in 文件的指示,configure 腳本檢查當前的系統環境和配置選項,在當前目錄中生成 Makefile 文件(還有其它無需關心的文件,移植軟件時要先配置,而後再修改Makefile文件),而後 make 程序就按照當前目錄中的 Makefile 文件的指示將源代碼編譯爲二進制文件,最後將這些二進制文件移動(即安裝)到指定的地方(仍然按照 Makefile 文件的指示)。

 

因而可知 Makefile 文件是幕後的核心。要深刻理解安裝過程,必須首先對 Makefile 文件有充分的瞭解。這裏將首先講述 Makefile 與 make ,而後再講述 configure 腳本。而且在講述這兩部份內容時,提供了儘量詳細的、能夠運用於實踐的參考資料。

 

Makefile 與 make緩存

 

 

用一句話來歸納Makefile 與 make 的關係就是:Makefile 包含了全部的規則和目標,而 make 則是爲了完成目標而去解釋 Makefile 規則的工具。

 

make 語法ide

 

首先看看 make 的命令行語法:

 

make [options] [targets] [VAR=VALUE]...

 

[options]是命令行選項,能夠用 make --help 命令查看所有,[VAR=VALUE]是在命令行上指定環境變量,這兩個你們都很熟悉,將在稍後詳細講解。而[targets]是什麼呢?字面的意思是"目標",也就是但願本次 make 命令所完成的任務。

 

憑經驗猜想,這個[targets]大概能夠用"check","install"之類(也就是常見的測試和安裝命令)。可是它究竟是個啥玩意兒?不帶任何"目標"的 make 命令是什麼意思?爲何在安裝 LFS 工具鏈中的 Perl-5.8.8 軟件包時會出現"make perl utilities"這樣怪異的命令?要回答這些問題必須首先理解 Makefile 文件中的"規則"。

 

 

Makefile 規則函數

 

Makefile 規則包含了文件之間的依賴關係和更新此規則目標所須要的命令。

一個簡單的 Makefile 規則是這樣寫的:

 

TARGET : PREREQUISITES
COMMAND

TARGET工具

        規則的目標。也就是能夠被 make 使用的"目標"。有些目標能夠沒有依賴而只有動做(命令行),好比"clean",一般僅僅定義一系列刪除中間文件的命令。一樣,有些目標能夠沒有動做而只有依賴,好比"all",一般僅僅用做"終極目標"。測試

PREREQUISITESui

        規則的依賴。一般一個目標依賴於一個或者多個文件。命令行

COMMANDdebug

        規則的命令行。一個規則能夠有零個或多個命令行。調試

 

OK! 如今你明白[targets]是什麼了,原來它們來自於 Makefile 文件中一條條規則的目標(TARGET)。另外,Makefile文件中第一條規則的目標被稱爲"終極目標",也就是你省略[targets]參數時的目標(一般爲"all")。

 

當你查看一個實際的 Makefile 文件時,你會發現有些規則很是複雜,可是它都符合規則的基本格式。此外,Makefile 文件中一般還包含了除規則之外的其它不少東西,不過這裏只關心其中的變量。

Makefile 變量

 

 

Makefile 中的"變量"更像是 C 語言中的宏,表明一個文本字符串(變量的值),能夠用於規則的任何部分。變量的定義很簡單:

 

VAR=VALUE;變量的引用也很簡單:$(VAR) 或者 ${VAR}。變量引用的展開過程是嚴格的文本替換過程,就是說變量值的字符串被精確的展開在變量被引用的地方。

 

好比,若定義:VAR=c,那麼,"$(VAR) $(VAR)-$(VAR) VAR.$(VAR)"將被展開爲"c c-c VAR.c"。

 

雖然在 Makefile 中能夠直接使用系統的環境變量,可是也能夠經過在 Makefile 中定義同名變量來"遮蓋"系統的環境變量。另外一方面,咱們能夠在調用 make 時使用  -e 參數強制使系統中的環境變量覆蓋 Makefile 中的同名變量,除此以外,在調用 make 的命令行上使用 VAR=VALUE 格式指定的環境變量也能夠覆蓋 Makefile 中的同名變量(在移植軟件時經常使用來修改交叉編譯器)。

 

Makefile 實例

下面看一個簡單的、實際的Makefile文件:

 

1.CC=gcc  

2.CPPFLAGS=  

3.CFLAGS=-O2 -pipe  

4.LDFLAGS=-s  

5.PREFIX=/usr  

6.  

7.all : prog1 prog2  

8.  

9.prog1 : prog1.o  

10.    $(CC) $(LDFLAGS) -o prog1 prog1.o  

11.  

12.prog1.o : prog1.c  

13.    $(CC) -c $(CFLAGS) prog1.c  

14.  

15.prog2 : prog2.o  

16.    $(CC) $(CFLAGS) $(LDFLAGS) -o prog2 prog2.o  

17.  

18.prog2.o : prog2.c  

19.    $(CC) -c $(CPPFLAGS) $(CFLAGS) prog2.c  

20.  

21.clean :  

22.    rm -f *.{o,a} prog{1,2}  

23.  

24.install : prog1 prog2  

25.    if ( test ! -d $(PREFIX)/bin ) ; then mkdir -p $(PREFIX)/bin ; fi  

26.    cp -f prog1 $(PREFIX)/bin/prog1  

27.    cp -f prog2 $(PREFIX)/bin/prog2  

28.  

29.check test : prog1 prog2  

30.    prog1 < sample1.ref > sample1.rz  

31.    prog1 < sample2.ref > sample3.rz  

32.    cmp sample1.ok sample1.rz  

33.    cmp sample2.ok sample2.rz  

 

從中能夠看出,make 與 make all 以及 make prog1 prog2 三條命令實際上是等價的。而經常使用的 make check 和 make install 也找到了歸屬。同時咱們也看到了 Makefile 中的各類變量是如何影響編譯的。針對這個特定的 Makefile ,你甚至能夠省略安裝三步曲中的 make 命令而直接使用 make install 進行安裝。

 

一樣,爲了使用自定義的編譯參數編譯 prog2 ,咱們可使用 make prog2 CFLAGS="-O3 -march=athlon64" 或 CFLAGS="-O3 -march=athlon64" && make -e prog2 命令達到此目的。

 

Makefile 慣例

 

 

下面是Makefile中一些約定俗成的目標名稱及其含義:

all

  • 編譯整個軟件包,但不重建任何文檔。通常此目標做爲默認的終極目標。此目標通常對全部源程序的編譯和鏈接使用"-g"選項,以使最終的可執行程序中包含調試信息。可以使用 strip 程序去掉這些調試符號。

clean

  • 清除當前目錄下在 make 過程當中產生的文件。它不能刪除軟件包的配置文件,也不能刪除 build 時建立的那些文件。

distclean

  • 相似於"clean",但增長刪除當前目錄下的的配置文件、build 過程產生的文件。

info

  • 產生必要的 Info 文檔。

check 或 test

  • 完成全部的自檢功能。在執行檢查以前,應確保全部程序已經被建立(但能夠還沒有安裝)。爲了進行測試,須要實如今程序沒有安裝的狀況下被執行的測試命令。

install

  • 完成程序的編譯並將最終的可執行程序、庫文件等拷貝到指定的目錄。此種安裝通常不對可執行程序進行 strip 操做。

install-strip

  • 和"install"相似,可是會對複製到安裝目錄下的可執行文件進行 strip 操做。

uninstall

  • 刪除全部由"install"安裝的文件。

installcheck

  • 執行安裝檢查。在執行安裝檢查以前,須要確保全部程序已經被建立而且被安裝。

installdirs

  • 建立安裝目錄及其子目錄。它不能更改軟件的編譯目錄,而僅僅是建立程序的安裝目錄。

     

下面是 Makefile 中一些約定俗成的變量名稱及其含義:

 

這些約定俗成的變量分爲三類。第一類表明可執行程序的名字,例如 CC 表明編譯器這個可執行程序;第二類表明程序使用的參數(多個參數使用空格分開),例如 CFLAGS 表明編譯器執行時使用的參數(一種怪異的作法是直接在 CC 中包含參數);第三類表明安裝目錄,例如 prefix 等等,含義簡單,下面只列出它們的默認值。

 

1.AR   函數庫打包程序,可建立靜態庫.a文檔。默認是"ar"。  

2.AS   彙編程序。默認是"as"。  

3.CC   C編譯程序。默認是"cc"。  

4.CXX  C++編譯程序。默認是"g++"。  

5.CPP  C/C++預處理器。默認是"$(CC) -E"。  

6.FC   Fortran編譯器。默認是"f77"。  

7.PC   Pascal語言編譯器。默認是"pc"。  

8.YACC Yacc文法分析器。默認是"yacc"。  

9.  

10.ARFLAGS     函數庫打包程序的命令行參數。默認值是"rv"。  

11.ASFLAGS     彙編程序的命令行參數。  

12.CFLAGS      C編譯程序的命令行參數。  

13.CXXFLAGS    C++編譯程序的命令行參數。  

14.CPPFLAGS    C/C++預處理器的命令行參數。  

15.FFLAGS      Fortran編譯器的命令行參數。  

16.PFLAGS      Pascal編譯器的命令行參數。  

17.YFLAGS      Yacc文法分析器的命令行參數。  

18.LDFLAGS     連接器的命令行參數。  

19.  

20.prefix      /usr/local  

21.exec_prefix $(prefix)  

22.bindir      $(exec_prefix)/bin  

23.sbindir     $(exec_prefix)/sbin  

24.libexecdir  $(exec_prefix)/libexec  

25.datadir     $(prefix)/share  

26.sysconfdir  $(prefix)/etc  

make 選項

最後說說 make 的命令行選項(以Make-3.81版本爲準):

-B, --always-make

  • 無條件的重建全部規則的目標,而不是根據規則的依賴關係決定是否重建某些目標文件。

-C DIR, --directory=DIR

  • 在作任何動做以前先切換工做目錄到 DIR ,而後再執行 make 程序。

-d

  • 在 make 執行過程當中打印出全部的調試信息。包括:make 認爲那些文件須要重建;那些文件須要比較它們的最後修改時間、比較的結果;重建目標所要執行的命令;使用的隱含規則等。使用該選項咱們能夠看到 make 構造依賴關係鏈、重建目標過程的全部信息,它等效於"-debug=a"。

--debug=FLAGS

    • 在 make 執行過程當中打印出調試信息。FLAGS 用於控制調試信息級別:

a

    • 輸出全部類型的調試信息

b

    • 輸出基本調試信息。包括:那些目標過時、是否重建成功過時目標文件。

v

    • 除 b 級別之外還包括:解析的 makefile 文件名,不須要重建文件等。

i

    • 除 b 級別之外還包括:全部使用到的隱含規則描述。

j

    • 輸出全部執行命令的子進程,包括命令執行的 PID 等。

m

    • 輸出 make 讀取、更新、執行 makefile 的信息

 

-e, --environment-overrides

  • 使用系統環境變量的定義覆蓋 Makefile 中的同名變量定義。

 

-f FILE, --file=FILE, --makefile=FILE

  • 將 FILE 指定爲 Makefile 文件。

 

-h, --help

  • 打印幫助信息。

 

-i, --ignore-errors

  • 忽略規則命令執行過程當中的錯誤。

 

-I DIR, --include-dir=DIR

  • 指定包含 Makefile 文件的搜索目錄。使用多個"-I"指定目錄時,搜索目錄按照指定順序進行。

 

-j [N], --jobs[=N]

  • 指定並行執行的命令數目。在沒有指定"-j"參數的狀況下,執行的命令數目將是系統容許的最大可能數目。

 

-k, --keep-going

  • 碰見命令執行錯誤時不終止 make 的執行,也就是儘量執行全部的命令,直到出現致命錯誤才終止。

 

-l [N], --load-average[=N], --max-load[=N]

  • 若是系統負荷超過 LOAD(浮點數),再也不啓動新任務。

 

-L, --check-symlink-times

  • 同時考察符號鏈接的時間戳和它所指向的目標文件的時間戳,以二者中較晚的時間戳爲準。

 

-n, --just-print, --dry-run, --recon

  • 只打印出所要執行的命令,但並不實際執行命令。

 

-o FILE, --old-file=FILE, --assume-old=FILE

  • 即便相對於它的依賴已通過期也不重建 FILE 文件;同時也不重建依賴於此文件任何文件。

 

-p, --print-data-base

  • 命令執行以前,打印出 make 讀取的 Makefile 的全部數據(包括規則和變量的值),同時打印出 make 的版本信息。若是隻須要打印這些數據信息,可使用 make -qp 命令。查看 make 執行前的預設規則和變量,可以使用命令 make -p -f /dev/null 。

 

-q, --question

  • "詢問模式"。不運行任何命令,而且無輸出,只是返回一個查詢狀態。返回狀態爲 0 表示沒有目標須要重建,1 表示存在須要重建的目標,2 表示有錯誤發生。

 

-r, --no-builtin-rules

  • 取消全部內嵌的隱含規則,不過你能夠在 Makefile 中使用模式規則來定義規則。同時還會取消全部支持後追規則的隱含後綴列表,一樣咱們也能夠在 Makefile 中使用".SUFFIXES"定義咱們本身的後綴規則。此選項不會取消 make 內嵌的隱含變量。

 

-R, --no-builtin-variables

  • 取消 make 內嵌的隱含變量,不過咱們能夠在 Makefile 中明肯定義某些變量。注意,此選項同時打開了"-r"選項。由於隱含規則是之內嵌的隱含變量爲基礎的。

 

-s, --silent, --quiet

  • 不顯示所執行的命令。

 

-S, --no-keep-going, --stop

  • 取消"-k"選項。在遞歸的 make 過程當中子 make 經過 MAKEFLAGS 變量繼承了上層的命令行選項。咱們能夠在子 make 中使用"-S"選項取消上層傳遞的"-k"選項,或者取消系統環境變量 MAKEFLAGS 中的"-k"選項。

 

-t, --touch

  • 更新全部目標文件的時間戳到當前系統時間。防止 make 對全部過期目標文件的重建。

 

-v, --version

  • 打印版本信息。

 

-w, --print-directory

  • 在 make 進入一個目錄以前打印工做目錄。使用"-C"選項時默認打開這個選項。

 

--no-print-directory

  • 取消"-w"選項。能夠是用在遞歸的 make 調用過程當中,取消"-C"參數將默認打開"-w"。

 

-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE

  • 設定 FILE 文件的時間戳爲當前時間,但不改變文件實際的最後修改時間。此選項主要是爲實現了對全部依賴於 FILE 文件的目標的強制重建。

 

--warn-undefined-variables

  • 在發現 Makefile 中存在對未定義的變量進行引用時給出告警信息。此功能能夠幫助咱們調試一個存在多級套嵌變量引用的複雜 Makefile 。可是:咱們建議在書寫 Makefile 時儘可能避免超過三級以上的變量套嵌引用。

configure

此階段的主要目的是生成 Makefile 文件,是最關鍵的指揮若定階段,基本上全部能夠對安裝過程進行的個性化調整都集中在這一步。

 

configure 腳本可以對 Makefile 中的哪些內容產生影響呢?基本上能夠這麼說:全部內容,包括這裏最關心的 Makefile 規則與 Makefile 變量。那麼又是哪些因素影響着最終生成的 Makefile 文件呢?答曰:系統環境和配置選項。

 

配置選項的影響是顯而易見的。可是"系統環境"的概念卻很寬泛,包含不少方面內容,不過咱們這裏只關心環境變量,具體說來就是未來會在 Makefile 中使用到的環境變量以及與 Makefile 中的變量同名的環境變量。

 

通用 configure 語法

在進一步講述以前,先看看 configure 腳本的語法,通常有兩種:

 

configure [OPTIONS] [VAR=VALUE]...

configure [OPTIONS] [HOST]

 

無論是哪一種語法,咱們均可以用 configure --help 查看全部可用的[OPTIONS],而且一般在結尾部分還能看到這個腳本所關心的環境變量有哪些。在這裏將對這兩種語法進行合併,使用下面這種簡化的語法:

 

configure [OPTIONS]

 

這種語法可以被全部的 configure 腳本所識別,同時也能經過設置環境變量和使用特定的[OPTIONS]完成上述兩種語法的一切功能。

 

通用 configure 選項

 

雖然每一個軟件包的 configure 腳本千差萬別,可是它們卻都有一些共同的選項,也基本上都遵照相同的選項語法。

腳本自身選項

--help

  • 顯示幫助信息。

--version

  • 顯示版本信息。

--cache-file=FILE

  • 在FILE文件中緩存測試結果(默認禁用)。

--no-create

  • configure腳本運行結束後不輸出結果文件,經常使用於正式編譯前的測試。

--quiet, --silent

  • 不顯示腳本工做期間輸出的"checking ..."消息。

     

 

目錄選項

--srcdir=DIR

  • 源代碼文件所在目錄,默認爲configure腳本所在目錄或其父目錄。

--prefix=PREFIX

  • 體系無關文件的頂級安裝目錄PREFIX ,默認值通常是 /usr/local 或 /usr/local/pkgName

--exec-prefix=EPREFIX

  • 體系相關文件的頂級安裝目錄EPREFIX ,默認值通常是 PREFIX

--bindir=DIR

  • 用戶可執行文件的存放目錄DIR ,默認值通常是 EPREFIX/bin

--sbindir=DIR

  • 系統管理員可執行目錄DIR ,默認值通常是 EPREFIX/sbin

--libexecdir=DIR

  • 程序可執行目錄DIR ,默認值通常是 EPREFIX/libexec

--datadir=DIR

  • 通用數據文件的安裝目錄DIR ,默認值通常是 PREFIX/share

--sysconfdir=DIR

  • 只讀的單一機器數據目錄DIR ,默認值通常是 PREFIX/etc

--sharedstatedir=DIR

  • 可寫的體系無關數據目錄DIR ,默認值通常是 PREFIX/com

--localstatedir=DIR

  • 可寫的單一機器數據目錄DIR ,默認值通常是 PREFIX/var

--libdir=DIR

  • 庫文件的安裝目錄DIR ,默認值通常是 EPREFIX/lib

--includedir=DIR

  • C頭文件目錄DIR ,默認值通常是 PREFIX/include

--oldincludedir=DIR

  • 非gcc的C頭文件目錄DIR ,默認值通常是 /usr/include

--infodir=DIR

  • Info文檔的安裝目錄DIR ,默認值通常是 PREFIX/info

--mandir=DIR

  • Man文檔的安裝目錄DIR ,默認值通常是 PREFIX/man

 

體系結構選項

玩交叉編譯的朋友對這些選項已經很熟悉了,對於不使用交叉編譯的朋友也沒必要擔憂,不要理它們就能夠了。

--build=BUILD

  • 工具鏈當前的運行環境,默認是 config.guess 腳本的輸出結果。

--host=HOST

  • 編譯出的二進制代碼將要運行在HOST上,默認值是BUILD。

--target=TARGET

  • 編譯出的工具鏈所未來生成的二進制代碼要在TARGET上運行,這個選項僅對工具鏈(也就是GCC和Binutils二者)有意義。

 

特性選項

--enable-FEATURE

  • 啓用FEATURE特性

--disable-FEATURE

  • 禁用FEATURE特性

--with-PACKAGE[=DIR]

  • 啓用附加軟件包PACKAGE,亦可同時指定PACKAGE所在目錄DIR

  • --without-PACKAGE

  • 禁用附加軟件包PACKAGE

 

通用環境變量

除了上述通用的選項外,下列環境變量影響着最終生成的 Makefile 文件:

CPP

  • C預處理器命令

CXXCPP

  • C++預處理器命令

CPPFLAGS

  • C/C++預處理器命令行參數

CC

  • C編譯器命令

CFLAGS

  • C編譯器命令行參數

CXX

  • C++編譯器命令

CXXFLAGS

  • C++編譯器命令行參數

LDFLAGS

  • 鏈接器命令行參數

至於設置這些環境變量的方法,你能夠將它們 export 爲全局變量在全局範圍內使用,也能夠在命令行上使用 [VAR=VALUE]... configure [OPTIONS] 的語法局部使用。今天就不詳細描述了。

相關文章
相關標籤/搜索