<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    【永恒的瞬間】
    ?Give me hapy ?

    前言

    從源代碼安裝過軟件的朋友一定對 ./configure && make && make install 安裝三步曲非常熟悉了。然而究竟這個過程中的每一步幕后都發(fā)生了些什么呢?本文將帶領(lǐng)你一探究竟。深入理解這個過程將有助于你在LFS的基礎(chǔ)上玩出自己的花樣來。不過需要說明的是本文對 Makefile 和 make 的講解是相當近視和粗淺的,但是對于理解安裝過程來說足夠了。

    概述

    用一句話來解釋這個過程就是:

    根據(jù)源碼包中 Makefile.in 文件的指示,configure 腳本檢查當前的系統(tǒng)環(huán)境和配置選項,在當前目錄中生成 Makefile 文件(還有其它本文無需關(guān)心的文件),然后 make 程序就按照當前目錄中的 Makefile 文件的指示將源代碼編譯為二進制文件,最后將這些二進制文件移動(即安裝)到指定的地方(仍然按照 Makefile 文件的指示)。

    由此可見 Makefile 文件是幕后的核心。要深入理解安裝過程,必須首先對 Makefile 文件有充分的了解。本文將首先講述 Makefile 與 make ,然后再講述 configure 腳本。并且在講述這兩部分內(nèi)容時,提供了盡可能詳細的、可以運用于實踐的參考資料。

    Makefile 與 make

    用一句話來概括Makefile 與 make 的關(guān)系就是:
    Makefile 包含了所有的規(guī)則和目標,而 make 則是為了完成目標而去解釋 Makefile 規(guī)則的工具。

    make 語法

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

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

    [options]是命令行選項,可以用 make --help 命令查看全部,[VAR=VALUE]是在命令行上指定環(huán)境變量,這兩個大家都很熟悉,將在稍后詳細講解。而[targets]是什么呢?字面的意思是"目標",也就是希望本次 make 命令所完成的任務(wù)。憑經(jīng)驗猜測,這個[targets]大概可以用"ckeck","install"之類(也就是常見的測試和安裝命令)。但是它到底是個啥玩意兒?不帶任何"目標"的 make 命令是什么意思?為什么在安裝 LFS 工具鏈中的 Perl-5.8.8 軟件包時會出現(xiàn)"make perl utilities"這樣怪異的命令?要回答這些問題必須首先理解 Makefile 文件中的"規(guī)則"。

    Makefile 規(guī)則

    Makefile 規(guī)則包含了文件之間的依賴關(guān)系和更新此規(guī)則目標所需要的命令。

    一個簡單的 Makefile 規(guī)則是這樣寫的:

    TARGET : PREREQUISITES
    COMMAND
    
    TARGET
    規(guī)則的目標。也就是可以被 make 使用的"目標"。有些目標可以沒有依賴而只有動作(命令行),比如"clean",通常僅僅定義一系列刪除中間文件的命令。同樣,有些目標可以沒有動作而只有依賴,比如"all",通常僅僅用作"終極目標"。
    PREREQUISITES
    規(guī)則的依賴。通常一個目標依賴于一個或者多個文件。
    COMMAND
    規(guī)則的命令行。一個規(guī)則可以有零個或多個命令行。

    OK! 現(xiàn)在你明白[targets]是什么了,原來它們來自于 Makefile 文件中一條條規(guī)則的目標(TARGET)。另外,Makefile文件中第一條規(guī)則的目標被稱為"終極目標",也就是你省略[targets]參數(shù)時的目標(通常為"all")。

    當你查看一個實際的 Makefile 文件時,你會發(fā)現(xiàn)有些規(guī)則非常復雜,但是它都符合規(guī)則的基本格式。此外,Makefile 文件中通常還包含了除規(guī)則以外的其它很多東西,不過本文只關(guān)心其中的變量。

    Makefile 變量

    Makefile 中的"變量"更像是 C 語言中的宏,代表一個文本字符串(變量的值),可以用于規(guī)則的任何部分。變量的定義很簡單:VAR=VALUE;變量的引用也很簡單:$(VAR) 或者 ${VAR}。變量引用的展開過程是嚴格的文本替換過程,就是說變量值的字符串被精確的展開在變量被引用的地方。比如,若定義:VAR=c,那么,"$(VAR) $(VAR)-$(VAR) VAR.$(VAR)"將被展開為"c c-c VAR.c"。

    雖然在 Makefile 中可以直接使用系統(tǒng)的環(huán)境變量,但是也可以通過在 Makefile 中定義同名變量來"遮蓋"系統(tǒng)的環(huán)境變量。另一方面,我們可以在調(diào)用 make 時使用 -e 參數(shù)強制使系統(tǒng)中的環(huán)境變量覆蓋 Makefile 中的同名變量,除此之外,在調(diào)用 make 的命令行上使用 VAR=VALUE 格式指定的環(huán)境變量也可以覆蓋 Makefile 中的同名變量。

    Makefile 實例

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

    CC=gcc
    CPPFLAGS=
    CFLAGS=-O2 -pipe
    LDFLAGS=-s
    PREFIX=/usr
    all : prog1 prog2
    prog1 : prog1.o
    $(CC) $(LDFLAGS) -o prog1 prog1.o
    prog1.o : prog1.c
    $(CC) -c $(CFLAGS) prog1.c
    prog2 : prog2.o
    $(CC) $(CFLAGS) $(LDFLAGS) -o prog2 prog2.o
    prog2.o : prog2.c
    $(CC) -c $(CPPFLAGS) $(CFLAGS) prog2.c
    clean :
    rm -f *.{o,a} prog{1,2}
    install : prog1 prog2
    if ( test ! -d $(PREFIX)/bin ) ; then mkdir -p $(PREFIX)/bin ; fi
    cp -f prog1 $(PREFIX)/bin/prog1
    cp -f prog2 $(PREFIX)/bin/prog2
    check test : prog1 prog2
    prog1 < sample1.ref > sample1.rz
    prog1 < sample2.ref > sample3.rz
    cmp sample1.ok sample1.rz
    cmp sample2.ok sample2.rz
    

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

    同樣,為了使用自定義的編譯參數(shù)編譯 prog2 ,我們可以使用 make prog2 CFLAGS="-O3 -march=athlon64" 或 CFLAGS="-O3 -march=athlon64" && make -e prog2 命令達到此目的。

    Makefile 慣例

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

    all
    編譯整個軟件包,但不重建任何文檔。一般此目標作為默認的終極目標。此目標一般對所有源程序的編譯和連接使用"-g"選項,以使最終的可執(zhí)行程序中包含調(diào)試信息??墒褂?strip 程序去掉這些調(diào)試符號。
    clean
    清除當前目錄下在 make 過程中產(chǎn)生的文件。它不能刪除軟件包的配置文件,也不能刪除 build 時創(chuàng)建的那些文件。
    distclean
    類似于"clean",但增加刪除當前目錄下的的配置文件、build 過程產(chǎn)生的文件。
    info
    產(chǎn)生必要的 Info 文檔。
    check 或 test
    完成所有的自檢功能。在執(zhí)行檢查之前,應(yīng)確保所有程序已經(jīng)被創(chuàng)建(但可以尚未安裝)。為了進行測試,需要實現(xiàn)在程序沒有安裝的情況下被執(zhí)行的測試命令。
    install
    完成程序的編譯并將最終的可執(zhí)行程序、庫文件等拷貝到指定的目錄。此種安裝一般不對可執(zhí)行程序進行 strip 操作。
    install-strip
    和"install"類似,但是會對復制到安裝目錄下的可執(zhí)行文件進行 strip 操作。
    uninstall
    刪除所有由"install"安裝的文件。
    installcheck
    執(zhí)行安裝檢查。在執(zhí)行安裝檢查之前,需要確保所有程序已經(jīng)被創(chuàng)建并且被安裝。
    installdirs
    創(chuàng)建安裝目錄及其子目錄。它不能更改軟件的編譯目錄,而僅僅是創(chuàng)建程序的安裝目錄。

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

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

    AR   函數(shù)庫打包程序,可創(chuàng)建靜態(tài)庫.a文檔。默認是"ar"。
    AS   匯編程序。默認是"as"。
    CC   C編譯程序。默認是"cc"。
    CXX  C++編譯程序。默認是"g++"。
    CPP  C/C++預(yù)處理器。默認是"$(CC) -E"。
    FC   Fortran編譯器。默認是"f77"。
    PC   Pascal語言編譯器。默認是"pc"。
    YACC Yacc文法分析器。默認是"yacc"。
    ARFLAGS     函數(shù)庫打包程序的命令行參數(shù)。默認值是"rv"。
    ASFLAGS     匯編程序的命令行參數(shù)。
    CFLAGS      C編譯程序的命令行參數(shù)。
    CXXFLAGS    C++編譯程序的命令行參數(shù)。
    CPPFLAGS    C/C++預(yù)處理器的命令行參數(shù)。
    FFLAGS      Fortran編譯器的命令行參數(shù)。
    PFLAGS      Pascal編譯器的命令行參數(shù)。
    YFLAGS      Yacc文法分析器的命令行參數(shù)。
    LDFLAGS     鏈接器的命令行參數(shù)。
    prefix      /usr/local
    exec_prefix $(prefix)
    bindir      $(exec_prefix)/bin
    sbindir     $(exec_prefix)/sbin
    libexecdir  $(exec_prefix)/libexec
    datadir     $(prefix)/share
    sysconfdir  $(prefix)/etc
    sharedstatedir $(prefix)/com
    localstatedir  $(prefix)/var
    libdir      $(exec_prefix)/lib
    infodir     $(prefix)/info
    includedir  $(prefix)/include
    oldincludedir  $(prefix)/include
    mandir      $(prefix)/man
    srcdir      需要編譯的源文件所在的目錄,無默認值
    

    make 選項

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

    -B, --always-make
    無條件的重建所有規(guī)則的目標,而不是根據(jù)規(guī)則的依賴關(guān)系決定是否重建某些目標文件。
    -C DIR, --directory=DIR
    在做任何動作之前先切換工作目錄到 DIR ,然后再執(zhí)行 make 程序。
    -d
    在 make 執(zhí)行過程中打印出所有的調(diào)試信息。包括:make 認為那些文件需要重建;那些文件需要比較它們的最后修改時間、比較的結(jié)果;重建目標所要執(zhí)行的命令;使用的隱含規(guī)則等。使用該選項我們可以看到 make 構(gòu)造依賴關(guān)系鏈、重建目標過程的所有信息,它等效于"-debug=a"。
    --debug=FLAGS
    在 make 執(zhí)行過程中打印出調(diào)試信息。FLAGS 用于控制調(diào)試信息級別:
    a
    輸出所有類型的調(diào)試信息
    b
    輸出基本調(diào)試信息。包括:那些目標過期、是否重建成功過期目標文件。
    v
    除 b 級別以外還包括:解析的 makefile 文件名,不需要重建文件等。
    i
    除 b 級別以外還包括:所有使用到的隱含規(guī)則描述。
    j
    輸出所有執(zhí)行命令的子進程,包括命令執(zhí)行的 PID 等。
    m
    輸出 make 讀取、更新、執(zhí)行 makefile 的信息。
    -e, --environment-overrides
    使用系統(tǒng)環(huán)境變量的定義覆蓋 Makefile 中的同名變量定義。
    -f FILE, --file=FILE, --makefile=FILE
    將 FILE 指定為 Makefile 文件。
    -h, --help
    打印幫助信息。
    -i, --ignore-errors
    忽略規(guī)則命令執(zhí)行過程中的錯誤。
    -I DIR, --include-dir=DIR
    指定包含 Makefile 文件的搜索目錄。使用多個"-I"指定目錄時,搜索目錄按照指定順序進行。
    -j [N], --jobs[=N]
    指定并行執(zhí)行的命令數(shù)目。在沒有指定"-j"參數(shù)的情況下,執(zhí)行的命令數(shù)目將是系統(tǒng)允許的最大可能數(shù)目。
    -k, --keep-going
    遇見命令執(zhí)行錯誤時不終止 make 的執(zhí)行,也就是盡可能執(zhí)行所有的命令,直到出現(xiàn)致命錯誤才終止。
    -l [N], --load-average[=N], --max-load[=N]
    如果系統(tǒng)負荷超過 LOAD(浮點數(shù)),不再啟動新任務(wù)。
    -L, --check-symlink-times
    同時考察符號連接的時間戳和它所指向的目標文件的時間戳,以兩者中較晚的時間戳為準。
    -n, --just-print, --dry-run, --recon
    只打印出所要執(zhí)行的命令,但并不實際執(zhí)行命令。
    -o FILE, --old-file=FILE, --assume-old=FILE
    即使相對于它的依賴已經(jīng)過期也不重建 FILE 文件;同時也不重建依賴于此文件任何文件。
    -p, --print-data-base
    命令執(zhí)行之前,打印出 make 讀取的 Makefile 的所有數(shù)據(jù)(包括規(guī)則和變量的值),同時打印出 make 的版本信息。如果只需要打印這些數(shù)據(jù)信息,可以使用 make -qp 命令。查看 make 執(zhí)行前的預(yù)設(shè)規(guī)則和變量,可使用命令 make –p -f /dev/null 。
    -q, --question
    "詢問模式"。不運行任何命令,并且無輸出,只是返回一個查詢狀態(tài)。返回狀態(tài)為 0 表示沒有目標需要重建,1 表示存在需要重建的目標,2 表示有錯誤發(fā)生。
    -r, --no-builtin-rules
    取消所有內(nèi)嵌的隱含規(guī)則,不過你可以在 Makefile 中使用模式規(guī)則來定義規(guī)則。同時還會取消所有支持后追規(guī)則的隱含后綴列表,同樣我們也可以在 Makefile 中使用".SUFFIXES"定義我們自己的后綴規(guī)則。此選項不會取消 make 內(nèi)嵌的隱含變量。
    -R, --no-builtin-variables
    取消 make 內(nèi)嵌的隱含變量,不過我們可以在 Makefile 中明確定義某些變量。注意,此選項同時打開了"-r"選項。因為隱含規(guī)則是以內(nèi)嵌的隱含變量為基礎(chǔ)的。
    -s, --silent, --quiet
    不顯示所執(zhí)行的命令。
    -S, --no-keep-going, --stop
    取消"-k"選項。在遞歸的 make 過程中子 make 通過 MAKEFLAGS 變量繼承了上層的命令行選項。我們可以在子 make 中使用"-S"選項取消上層傳遞的"-k"選項,或者取消系統(tǒng)環(huán)境變量 MAKEFLAGS 中的"-k"選項。
    -t, --touch
    更新所有目標文件的時間戳到當前系統(tǒng)時間。防止 make 對所有過時目標文件的重建。
    -v, --version
    打印版本信息。
    -w, --print-directory
    在 make 進入一個目錄之前打印工作目錄。使用"-C"選項時默認打開這個選項。
    --no-print-directory
    取消"-w"選項??梢允怯迷谶f歸的 make 調(diào)用過程中,取消"-C"參數(shù)將默認打開"-w"。
    -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
    設(shè)定 FILE 文件的時間戳為當前時間,但不改變文件實際的最后修改時間。此選項主要是為實現(xiàn)了對所有依賴于 FILE 文件的目標的強制重建。
    --warn-undefined-variables
    在發(fā)現(xiàn) Makefile 中存在對未定義的變量進行引用時給出告警信息。此功能可以幫助我們調(diào)試一個存在多級套嵌變量引用的復雜 Makefile 。但是:我們建議在書寫 Makefile 時盡量避免超過三級以上的變量套嵌引用。

    configure

    此階段的主要目的是生成 Makefile 文件,是最關(guān)鍵的運籌帷幄階段,基本上所有可以對安裝過程進行的個性化調(diào)整都集中在這一步。

    configure 腳本能夠?qū)?Makefile 中的哪些內(nèi)容產(chǎn)生影響呢?基本上可以這么說:所有內(nèi)容,包括本文最關(guān)心的 Makefile 規(guī)則與 Makefile 變量。那么又是哪些因素影響著最終生成的 Makefile 文件呢?答曰:系統(tǒng)環(huán)境和配置選項。

    配置選項的影響是顯而易見的。但是"系統(tǒng)環(huán)境"的概念卻很寬泛,包含很多方面內(nèi)容,不過我們這里只關(guān)心環(huán)境變量,具體說來就是將來會在 Makefile 中使用到的環(huán)境變量以及與 Makefile 中的變量同名的環(huán)境變量。

    通用 configure 語法

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

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

    configure [OPTIONS] [HOST]

    不管是哪種語法,我們都可以用 configure --help 查看所有可用的[OPTIONS],并且通常在結(jié)尾部分還能看到這個腳本所關(guān)心的環(huán)境變量有哪些。在本文中將對這兩種語法進行合并,使用下面這種簡化的語法:

    configure [OPTIONS]

    這種語法能夠被所有的 configure 腳本所識別,同時也能通過設(shè)置環(huán)境變量和使用特定的[OPTIONS]完成上述兩種語法的一切功能。

    通用 configure 選項

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

    腳本自身選項

    --help
    顯示幫助信息。
    --version
    顯示版本信息。
    --cache-file=FILE
    在FILE文件中緩存測試結(jié)果(默認禁用)。
    --no-create
    configure腳本運行結(jié)束后不輸出結(jié)果文件,常用于正式編譯前的測試。
    --quiet, --silent
    不顯示腳本工作期間輸出的"checking ..."消息。

    目錄選項

    --srcdir=DIR
    源代碼文件所在目錄,默認為configure腳本所在目錄或其父目錄。
    --prefix=PREFIX
    體系無關(guān)文件的頂級安裝目錄PREFIX ,默認值一般是 /usr/local 或 /usr/local/pkgName
    --exec-prefix=EPREFIX
    體系相關(guān)文件的頂級安裝目錄EPREFIX ,默認值一般是 PREFIX
    --bindir=DIR
    用戶可執(zhí)行文件的存放目錄DIR ,默認值一般是 EPREFIX/bin
    --sbindir=DIR
    系統(tǒng)管理員可執(zhí)行目錄DIR ,默認值一般是 EPREFIX/sbin
    --libexecdir=DIR
    程序可執(zhí)行目錄DIR ,默認值一般是 EPREFIX/libexec
    --datadir=DIR
    通用數(shù)據(jù)文件的安裝目錄DIR ,默認值一般是 PREFIX/share
    --sysconfdir=DIR
    只讀的單一機器數(shù)據(jù)目錄DIR ,默認值一般是 PREFIX/etc
    --sharedstatedir=DIR
    可寫的體系無關(guān)數(shù)據(jù)目錄DIR ,默認值一般是 PREFIX/com
    --localstatedir=DIR
    可寫的單一機器數(shù)據(jù)目錄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

    體系結(jié)構(gòu)選項

    玩交叉編譯的朋友對這些選項已經(jīng)很熟悉了,并且對于通常的交叉編譯情況而言,HOST == BUILD != TARGET 。但是對于不使用交叉編譯的朋友也不必擔心,將它們?nèi)齻€都設(shè)為相同即可。

    --host=HOST
    運行工具鏈的機器,默認是 config.guess 腳本的輸出結(jié)果。
    --build=BUILD
    用來建立工具鏈的機器,默認值是 HOST
    --target=TARGET
    工具鏈所生成的二進制代碼最終運行的機器,默認值是 HOST

    特性選項

    --enable-FEATURE
    啟用FEATURE特性
    --disable-FEATURE
    禁用FEATURE特性
    --with-PACKAGE[=DIR]
    啟用附加軟件包PACKAGE,亦可同時指定PACKAGE所在目錄DIR
    --without-PACKAGE
    禁用附加軟件包PACKAGE

    通用環(huán)境變量

    除了上述通用的選項外,下列環(huán)境變量影響著最終生成的 Makefile 文件:

    CPP
    C預(yù)處理器命令
    CXXCPP
    C++預(yù)處理器命令
    CPPFLAGS
    C/C++預(yù)處理器命令行參數(shù)
    CC
    C編譯器命令
    CFLAGS
    C編譯器命令行參數(shù)
    CXX
    C++編譯器命令
    CXXFLAGS
    C++編譯器命令行參數(shù)
    LDFLAGS
    連接器命令行參數(shù)

    至于設(shè)置這些環(huán)境變量的方法,你可以將它們 export 為全局變量在全局范圍內(nèi)使用,也可以在命令行上使用 [VAR=VALUE]... configure [OPTIONS] 的語法局部使用。此處就不詳細描述了。

    posted on 2007-05-10 20:38 ???MengChuChen 閱讀(241) 評論(0)  編輯  收藏 所屬分類: Sun_Solaris
    主站蜘蛛池模板: 免费a级毛片大学生免费观看| 四虎在线成人免费网站| 成人国产mv免费视频| 国产亚洲精aa在线看| 青苹果乐园免费高清在线| 亚洲一区二区三区在线观看蜜桃| 久久久久免费看成人影片| 亚洲国产综合精品中文第一区| 久久大香伊焦在人线免费| 亚洲精品私拍国产福利在线| 国产精品99精品久久免费| 亚洲视频一区在线| 无码国产精品一区二区免费虚拟VR| 亚洲白色白色永久观看| 黄在线观看www免费看| 亚洲精品国产日韩| 国产在线不卡免费播放| 免费国产草莓视频在线观看黄| 亚洲?V无码乱码国产精品| 中文字幕a∨在线乱码免费看 | 毛片免费vip会员在线看| 亚洲一区二区三区深夜天堂| 午夜时刻免费入口| 成年免费a级毛片| 久久久久亚洲av无码尤物| 99无码人妻一区二区三区免费| 色天使亚洲综合在线观看| 亚洲av无码成人精品区| 国产中文字幕在线免费观看| 亚洲黄色三级视频| 国产精品免费视频一区| 久久久受www免费人成| 亚洲老熟女@TubeumTV| 日韩在线看片免费人成视频播放| 国产精品1024在线永久免费 | 亚洲一级毛片中文字幕| 日本无卡码免费一区二区三区| 成人免费一区二区三区| 亚洲午夜国产精品| 久久亚洲av无码精品浪潮| 亚洲电影在线免费观看|