makefile學習筆記

來源:互聯網
上載者:User

標籤:

make處 理Makefile的過程也分為兩個階段:

· 首先從前到後讀取所有規則,建立起一個完整的依賴關係圖

·然後從預設目標或者命令列指定的目標開始,根據依賴關係圖選擇適當的規則執行,執 行Makefile中的規則並不是從前到後按順序執行,也不是所有規則 都要執行一遍。首先更新它的所有條件;所有 條件中只要有一個條件被更新了,目標也必須隨之被更新。

寫Makefile都是以目標為中心,一個目標依賴於若干條件,現在換個角度,如下以條件為中 心 (makefile目的是讓make建立依賴關係圖,只要把所有的依賴關係描 述清楚就ok)

  main.o stack.o:stack.h

  main.o stack.o maze.o:main.h

  main.o maze.o:maze.h

註:在make的命令列中指定一個目標(例如clean),則更新這個目標,如果不指定目標則更 新Makefile中第一條規則的目標(預設目標)。

小常識:命令前面加@和-字元:如果make執行的命令前面加了@字元,則 不顯示命令本身而只顯示它的結果;make執行的命令如果出錯就 立刻終止,不再執行後續命令,但如果命令前面加了-號,即使這條命令出錯,make也會繼續執 行後續命令。通常rm命令和mkdir命令前面要加-號。

 

Makefile(裡主要包含了五個東西:顯式規則、隱晦規則、變數定義、檔案指示和注釋。)

預設情況,make命令會在目前的目錄下按順序找尋檔案名稱為“GNUmakefile”、“makefile”、“Makefile”的檔案,找到瞭解釋這個檔案。在這三個檔案名稱中,最好使用“Makefile”這個檔案名稱,第一個字元為大寫有一種顯目的感覺。最好不要用“GNUmakefile”,這個檔案是GNU的make識別的。有另外一些make只對全小寫“makefile”檔案名稱敏感,但是基本上來說,大多數的make都支援“makefile”和“Makefile”這兩種預設檔案名稱。

當然,你可以使用別的檔案名稱來書寫Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,如果要指定特定的Makefile,你可以使用make的“-f”和“--file”參數,如:make -f Make.Linux或make --file Make.AIX。

一: 顯式規則。

  顯式規則說明如何產生一個或多的的目標檔案。這是由Makefile的書寫者明顯指出,要產生的檔案,檔案的依賴檔案,產生的命令。

  規則包含兩個部分,一個是依賴關係,一個是產生目標的方法。

  target.o : target.c target.h

    gcc -c target.c -o target.o

  檔案target.o依賴於target.c和target.h的檔案,如果target.c和target.h的檔案日期比target.o檔案日期新,或是target.o不存在,那麼依賴關係發生。

 

二、隱晦規則(make的隱含規則 資料庫可以用make -p命令列印)。

  一個目標依賴的所有條件不一定非得寫在一條規則中,也可以拆開寫(若一個目標拆開寫多條規則,其中只允許一條規則有命令列表,其它規則應該沒有命令列 表,否則make會警示告並且採用最後一條規則的命令列表)。

  target.o : target.h

  target.o : target.c

      gcc  -c  target.c  -o  target.o

  make有自動推導的功能,利用隱晦規則可以簡略書寫Makefile。

  上述等價於:target.o:target.h (沒有編譯命令時,makefile會嘗試內建的隱含命令)

  隱含規則中使用的變數分成兩種:一種是命令相關的,如“CC”;一種是參數相的關,如, “CFLAGS”。

關於命令的變數:AR  函數庫打包程式。預設命令是“ar”。  AS  組合語言編譯器。預設命令是“as”。 CC  C語言編譯器。預設命令是“cc”。 CXX  C 語言編譯器。預設命令是“g ”。 CO  從 RCS檔案中擴充檔案程式。預設命令是“co”。 CPP  C程式的前置處理器(輸出是標準輸出裝置)。預設命令是“$(CC) –E”。 FC  Fortran 和 Ratfor 的編譯器和預先處理程式。預設命令是“f77”。 GET  從SCCS檔案中擴充檔案的程式。預設命令是“get”。  LEX  Lex方法分析器程式(針對於C或Ratfor)。預設命令是“lex”。 PC  Pascal語言編譯器。預設命令是“pc”。 YACC  Yacc文法分析器(針對於C程式)。預設命令是“yacc”。 YACCR  Yacc文法分析器(針對於Ratfor程式)。預設命令是“yacc –r”。 MAKEINFO  轉換Texinfo源檔案(.texi)到Info檔案程式。預設命令是“makeinfo”。 TEX  從TeX源檔案建立TeX DVI檔案的程式。預設命令是“tex”。 TEXI2DVI  從Texinfo源檔案建立軍TeX DVI 檔案的程式。預設命令是“texi2dvi”。 WEAVE  轉換Web到TeX的程式。預設命令是“weave”。 CWEAVE  轉換C Web 到 TeX的程式。預設命令是“cweave”。 TANGLE  轉換Web到Pascal語言的程式。預設命令是“tangle”。 CTANGLE  轉換C Web 到 C。預設命令是“ctangle”。 RM  刪除檔案命令。預設命令是“rm –f”。

關於命令參數的變數: 下面的這些變數都是相關上面的命令的參數。如果沒有指明其預設值,那麼其預設值都是空。
ARFLAGS  函數庫打包程式AR命令的參數。預設值是“rv”。 ASFLAGS  組合語言編譯器參數。(當明顯地調用“.s”或“.S”檔案時)。  CFLAGS  C語言編譯器參數。 CXXFLAGS  C 語言編譯器參數。 COFLAGS  RCS命令參數。  CPPFLAGS  C前置處理器參數。( C 和 Fortran 編譯器也會用到)。 F, FLAGS  Fortran語言編譯器參數。 GFLAGS  SCCS “get”程式參數。 LDFLAGS  連結器參數。(如:“ld”) LFLAGS  Lex文法分析器參數。 PFLAGS  Pascal語言編譯器參數。 RFLAGS  Ratfor 程式的Fortran 編譯器參數。 YFLAGS  Yacc文法分析器參數。

三、變數的定義。

  在Makefile中我們要定義一系列的變數,當Makefile被執行時,其中的變數都會被擴充到相應的引用位置。

  3.1  如環境中定義了環境變數MAKEFILES,make會把這個變數中的值做一個類似於include的動作。這個變數中的值是其它的Makefile,用空格分隔。它和include不同的是,從這個環境變中引入的Makefile的“目標”不會起作用,如果環境變數中定義的檔案發現錯誤,make也會不理。建議不要使用這個環境變數,這個變數被定義後,當你使用make時,所有的Makefile都會受到它的影響。

  3.2 常規變數(“替代”原理)

 

    變數聲明時需要賦初值,在使用時,要在變數名前加“$”符號,最好"()"或是“{}”把變數給包括起來。若要使用真實的“$”字元,需用“$$”表示。

    有如下3種:1、變數賦值成一個常量(vars =  program.o foo.o utils.o);2 變數賦值成變數(變數是可以使用後面的變數來定義)(vars1 = $(vars2));3 變數賦值成變數(變數只能使用前面的變數來定義)(vars1 := $(vars));4根據條件賦值(以前不存在賦值則賦值)(vars3 ?= $(vars))

    註:"="和還有追加的意思。變數之前沒被定義,“ =”會自動變成“=”,如果有,那麼“ =”會繼承前次操作的賦值符。若前次是“:=”,那麼“ =”會以“:=”作為其賦值符。

    上述已經說明了:makefile第一步是建立起一個完整的依賴關係圖(“=”在第一步只建立關係,“:=”在第一步遇值展開)

    一個變數的值從定義它的’=‘或者’:=‘後邊的第一個非Null 字元開始,直到注釋或者換行前結束。(如下定義空格)

        nullstring :=

        space := $(nullstring) #end 

  3.3 自動變數

    [email protected]:規則中的目標檔案集

    $%:規則中的目標是函數庫檔案集(如果一個目標是"foo.a bar.o",那麼,"$%"就是"bar.o","[email protected]"就是"foo.a")

    $<:規則中的目標依賴的第一個依賴。如果依賴目標是以模式(即"%")定義的,那麼"$<"將是符合模式的一系列的檔案集(其實是一個一個取出來的)。

    $?:規則中的所有比目標新的依賴目標的集。

    $^:規則中的所有的依賴目標的集合。以空格分隔。如果在依賴目標中有多個重複的,那個這個變數會去除重複的依賴目標,只保留一份。

    $ :規則中的所有的依賴目標的集合。同"$^",只是它不去除重複的依賴目標。

    $*:規則中目標模式中"%"及其之前的部分。如果目標是"dir/a.foo.b",並且目標的模式是"a.%.b",那麼,"$*"的值就是"dir/a.foo"。

      註:如果目標中沒有模式的定義,那麼"$*"也就不能被推匯出。如果目標檔案的尾碼是make所識別的,那麼"$*"就是除了尾碼的那一部分。

          若目標是"foo.c",".c"是make所能識別的尾碼名,"$*"的值就是"foo"。這個特性是GNU make的,可能不相容其它版本make,應盡量避免使用"$*"。

    在上述所列出來的自動量變數中。四個變數([email protected]、$<、$%、$*)在擴充時只會有一個檔案,而另三個的值是一個檔案清單。這些自動化變數還可以取得檔案的目錄名或    是在目前的目錄下的符合模式的檔案名稱,只需要搭配上"D"或"F"字樣。這是 GNU make中老版本的特性,在新版本中,我們使用函數"dir"或"notdir"就可以做到了。"D"的含義就是Directory,就是目錄,"F"的 含義就是File,就是檔案。例:$(@D)"相當於函數"$(notdir [email protected])"。、$(@F)

  3.4 make命令列設定參數

    若變數是make的命令列參數設定的,那麼Makefile中對這個變數的賦值會被忽略。想在Makefile中設定這類參數的值,可以使用“override”指示符。其文法是:

    override para=value 或者override :para=value

    例子:

    (1)override gao += abc    (2)  gao += abc
        all:                all:
            @echo $(gao)            @echo $(gao)

    同時執行:make gao=12345 (1)結果是  12345 abc;(2)結果是 12345

   3.5 目標變數和模式變數

      目標變數為某個目標設定局部變數(作用範圍只在這條規則以及連帶規則中,不會影響規則鏈以外的全域變數的值)。

      模式變數是我們可以給定一種“模式”,可以把變數定義在符合這種模式的所有目標上(make的“模式”一般是至少含有一個“%”的)。

      target: PATA = -g 不管全域的$(PATA)的值是什麼,在prog目標,以及其所引發的所有$(CFLAGS)的值都是“-g”。

      %.o : PATA= -O  所有符合以[.o]結尾的目標中規則中$(PATA)的值都是“-O”。

  3.6  變數進階用法

      1.替換變數中共有部分,格式:“$(var:a=b)”或是“${va:a=b}”。含義:把變數“var”中所有以“a”字串“結尾”(“結尾”即“空格”或者“結束符”)的“a”替換成“b”字串。

      2.“靜態模式”替換。 $(val:%.o=%.c),這依賴於被替換字串中的有相同的模式.

四、檔案指示

  1.在一個Makefile中引用另一個Makefile,就像C語言中的include一樣

    在Makefile中引用其他Makefile檔案的方法是,使用inclue   filename.mk.

  2.根據某些情況指定Makefile中的有效部分,就像C語言中的先行編譯#if一樣

    “函數”與“條件陳述式”一同使用

     ifdef

       do_sort func := sort

     else

       func := strip endif

     bar := a d b g q c

      foo := $($(func) $(bar))

    這個樣本中,如果定義了“do_sort”,那麼$(foo)意思就是對%(bar)排序。沒有定義“do_sort”,那麼%(foo)意思就是對bar調用strip函數。

  3.還有就是定義一個多行的命令(define和endef)

    define指示符後面跟的是變數的名字,其工作方式和“=”操作符一樣。變數的值可以包含函數、命令、文字,或是其它變數。因為命令需要以[Tab]鍵開頭,所以如果你用define定義 的命令變數中沒有以[Tab]鍵開頭,那麼make就不會把其認為是命令。

    define two-lines
      echo foo
      echo $(bar)
    endef

5、注釋。Makefile中只有行注釋,和UNIX的Shell指令碼一樣,其注釋是用“#”字元,如果你要在你的Makefile中使用“#”字元,可以用反斜框進行轉義,如:“\#”。

 

 

makefile學習筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.