[工程構建][makefile] 基礎知識點

#1 make是一個命令,他會按照自己的規則執行名字爲Makefile、makefile或者之類的名字,或者通過 make -f 1.txt 這樣來指定執行一個文件。

#2 make命令解析文件的最基本、最重要的途徑就是如下格式:
    <target> : <prerequisites> 
    [tab]  <commands>
    
    對上面這兩行代碼的解讀:
    1 - 想要得到target,材料是prerequisites,工具是commands。
    2 - target是必須的,prerequisites和commands至少要有一個存在。
    3 - target可以有多個,像prerequisites一樣,多個目標之間用空格分割。
    
#3 注意:Makefile什麼都不是,我們面向的應該是make這個命令是如何使用的,Makefile只是按照make命令要求寫的一個標準格式文件。

#4 僞目標(用來指定非編譯動作,因爲正常情況下,make動作都會輸出目標文件,如果我想做某個動作而不是輸出目標文件,就要指定目標動作爲僞目標)
        clean:
             rm -rf *
      make動作是針對Makefile(或者-f指定一個文件)中的“目標”而言的,如果不指定,那麼就取“第一個目標”,如果指定,則取指定的目標。
   針對上面這種情況,有一個BUG,如果當前目錄中有一個叫做clean的文件,那麼make就會以爲下面的命令行是用來生成clean文件的,所以不會再去執行。針對這種情況,
   需要把clean明確指定爲僞目標:            .PHONY:clean
                                          clean:
                                                    rm -rf *
                                                    
#5 前置條件(材料)
    <target> : <prerequisites> 
    [tab]  <commands>
    只要前置條件列表和之前不一樣了,或者裏面的內容發生更新了,那麼就使用commands重新構建target。
        注:如果某個target後面沒有前置條件,那麼每次執行make <target>,commands都一定會執行。
        
#6 再說僞目標
  有時候也可以這樣用:當commands是空的時候,僞目標類似宏定義,比如 all:1.c 2.c 3.c ,此時make或者make all,相當於make 1.c ,make 2.c , make 3.c
  會依次執行all所指代的前置條件。
        注:這也是幾乎所有Makefile都在用的一點,需要輸出多個目標的時候,就先定一個總的來代替多個目標
        
#7 命令
   命令用來表示如何生成target,命令有一行或者多行“shell命令”組成。
   默認情況下命令前面要有TAB鍵,如果想換成別的,可以設置環境變量.RECIPEPREFIX,比如.RECIPEPREFIX = >
                                                                              all:
                                                                              > echo Hello, world
                                                                              
#8 “命令”注意要點
    命令可以有多行,但是不同於shell腳本,這多行是由多個進程一起執行的,所以相互之間沒有關聯。比如:
    all:
        export a=1
        echo $a
    針對上面這個文件,做make或者make all,無法正確獲得a的值。
    
    可以用如下幾種方法來解決:
    1 - 命令放在一行,用分號隔開
                     all:
                        export a=1;echo $a
    2 - 命令放在不同的行,用\連接
                     all:
                        export a=1 \
                        echo $a
    3 - 通過僞目標標註
                     .ONESHELL:
                     all:
                        export a=1
                        echo $a
    
#9 語法
     #9-1  “回聲”
           默認情況下,會向標準輸出打印每一條command。即使是以#開頭,都會打印(但是前置TAB不可少,少了就不是command了)。這叫做“回聲”
           如果想關閉,只需要在command前面加一個@就行了。
           實際工作過程中,一般會給command的註釋前面加上@
     #9-2  “通配符”
           和bash的通配符使用一樣,*,?,[1-2]等
     #9-3  “模式匹配”
            %.o: %.c代表對當前目錄下所有.c文件做.o依賴,比如當前目錄下有1.c和2.c,那麼以上的語句等於:
            
            1.o:1.c
            2.o:2.c
                
     #9-4  “變量和賦值”
            有四種賦值方式:
            1 - VARIABLE = value    # 在執行時擴展,允許遞歸擴展
            2 - VARIABLE := value    # 在定義時擴展
            3 - VARIABLE ?= value    # 只有在該變量爲空時才設置值
            4 - VARIABLE += value    # 將值追加到變量的尾端
            
     #9-5  “內置變量”
            提供了一些默認的環境變量,比如$(CC) 指向當前使用的編譯器,$(MAKE) 指向當前使用的Make工具。
            更多見https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
     
     #9-6  “自動變量”
            $@  -  當前commands對應的target
            $<  -  第一個prerequisites
            $?  -  較當前target時間點而言,所有更新過的prerequisites(比較有用,可以用來取到所有近期變動過的prerequisites)
            $^  -  指代所有的prerequisites
            $*  -  所有%匹配的文件名,無後綴(比如前面的 %o:%.c,在這個依賴關係的commands中使用$*,就指代所有的文件名,比如上例中的1 2)
            $(@D)和$(@F) - $(@D)指$@的路徑,$(@F)指$@的文件名
            $(<D)和$(<F) - $(<D)指$<的路徑,$(<F)指$<的文件名
            
     #9-7  “循環和判斷”
            語法同bash
            
     #9-8  “函數”
            有許多內置函數可在整個Makefile內使用(不侷限於target、prerequisites和commands,比如在做變量賦值時也可以用)
            格式爲: $(function arguments)
                    # 或者
                    ${function arguments}
            
            1 - shell函數(執行一個shell命令)
                例如  srcfiles := $(shell echo src/{00..99}.txt)
            2 - wildcard函數(用來在 Makefile 中,替換 Bash 的通配符 )
                例如  srcfiles := $(wildcard src/*.txt)
            3 - subst函數(用來文本替換)
                例如  將字符串"feet on the street"替換成"fEEt on the strEEt"
                        $(subst ee,EE,feet on the street)
            4 - patsubst函數(用於模式匹配的替換)
                例如  將文件名"x.c.c bar.c",替換成"x.c.o bar.o"
                        $(patsubst %.c,%.o,x.c.c bar.c)
            5 - (!!!常用!!!)替換後綴名
                例如  min:$(*.pc:=.c),把所有的pc結尾的文件,替換成c結尾

#10 ----------------------終-----------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章