Makefile筆記

命名

文件保存以Makefilemakefile爲名.當在當前目錄下直接輸入make便可執行vim

若是不是默認的文件名, 可使用-f參數安全

make -f make.some

變量

變量基本用法

  • 變量以=賦值
    左側是變量, 右側是變量的值bash

objects = main.o kbd.o command.o display.o \

也可使用變量來構造變量ide

A = $(B)
B = $(A)

如上所示, 會讓make陷入無限的變量展開過程當中, 報錯. 故可以使用下面的:=函數

  • 變量以$(objects)取值
    變量使用時要在前面加上$, 最好用()或者{}把變量括起來. 若是要使用真實的的$, 用$$ui

  • 變量以:=定義
    =有可能致使遞歸定義, 故使用該表達式, 前面的變量不使用後面的變量, 只使用已經定義好的變量編碼

  • 變量以?=定義.net

foo ?= bar

若是foo沒有被定義過, 那麼變量foo的值是bar, 不然, 這條語句什麼也不作.命令行

  • 追加變量+=
    若是變量以前沒有定義過, +=自動變爲=, 反之則繼承於前次的操做的賦值符. 前次是:=, 那麼這次爲:=; 前次爲=, 這次爲=code

  • override指示符變量
    override指示符的變量, 在make命令行參數中能夠設置, 而Makefile中對這個變量的賦值會被忽略

override <varriable> = <value>
override <varriable> := <value>

追加,

override <variable> += <more value>
  • 多行變量
    define指示符後面跟的是變量名稱, 而重起一行定義變量的值, 變量能夠換行, 定義以endef關鍵字結束. 變量的值能夠包含函數,命令,文字或者其餘變量

  • 環境變量
    make 運行時的系統環境變量能夠在 make 開始運行時被載入到 Makefile 文件中,可是
    若是 Makefile 中已定義了這個變量,或是這個變量由 make 命令行帶入,那麼系統的環
    境變量的值將被覆蓋。若是 make 指定了-e參數,那麼,系統環境變量將覆蓋
    Makefile 中定義的變量

變量高級用法

  • 變量值的替換
    替換變量中的共有部分, 格式爲$(var:a=b)或者${var:a=b}, 把var中全部以結尾的字串替換成以b結尾
    以下

foo := a.o b.o c.o
bar := $(foo:.o=.c)

定義了\${foo}變量,把\${foo}中全部以.o結尾的子串所有替換爲以.c結尾,$(bar)的值是a.c b.c c.c

  • 把變量值再再當成變量

x = y
y = z
a := $($(x))

如上, \$(x)的值是y, \$(\$(x))就是\$(y), 那\$(a)就是z

依賴規則

規則語法

targets : prerequisites
    command

targes是文件名, 以空格分開, 可使用通配符. 目標能夠是一個文件, 也多是多個文件.

command是命令行, 若是不與targets : prerequisites一行, 必須以[Tagb鍵]開頭, 若是在一行, 可用;分割, 以下

targets : prerequisites ; command

prerequisites是目標所依賴的文件(或者依賴目標), 若是有一個以上的文件比 target 文件要新的話,command 所定義的命令就會被執行

僞目標

僞目標的規則相似上面的規則, 可是僞目標不是文件, 只是一個標籤, 因此make沒法生成它的依賴關係和決定它是否執行, 只有經過顯示指定這個目標才能讓其生效.
好比, make clean科學能夠執行下面的命令.

clean :
    rm *.o temp

爲了不和文件重命的狀況, 使用特殊的額標記.PHONY來顯示的指明一個僞目標, 不論是否有同名文件

.PHONY : clean
clean : 
    rm *.o temp

僞目標沒有依賴文件 ,可是能夠爲僞目標指定所依賴的文件. 僞目標能夠做爲默認目標

.PHONY : all cleanall cleanobj
all : prog1 prog2

prog1 : prog1.o utils.o
    cc -o prog1 prog1.o util.o

prog2 : proj2.o 
    cc -o prog2 prog2.o

cleanall : cleanobj cleandiff
    rm program

cleanobj :
    rm *.o

dleandiff : 
    rm *.diff

Makefile中的第一目標會被當作默認目標. all僞目標依賴於其餘的三個目標

目標和僞目標均可以成爲依賴.

如上, make cleanall, make cleanobj均可以顯示僞目標執行命令

多目標

Makefile的規則中的目標能夠不止一個, 其支持多目標. 當讓, 有自動化變量$@吧表示目標的集合, 依次取出目標, 並執行命令.以下

bigoutput littleoutput : text.g
generate text.g $@ > $@

靜態模式定義的多目標

語法以下

<targets...> : <target-pattern> : <prereq-pattern>
<commmands>
  • targets 定義了一系列目標, 能夠有通配符, 是目標的一個集合

  • targets-pattern 指明瞭目標集模式, 從目標集中選出一部分目標

  • prereq-pattern 是目標的依賴模式, 對target-pattern造成的模式再次進行依賴目標的定義, 對選出的目標進行再定義

For example.

objects = foo.o bar.o
all : $(objects)
$(objects) : %.o : %.c
$(CC) -c $< -o $@

從目標集foo.o bar.o中經過%.o的目標集模式選出以後, 經過%.c進行二次定義.

  • %<自動化變量, 表示全部的依賴目標, 用%c表示

  • %@表示目標集, 即%.o

規則中使用通配符

同bash同樣, 支持三種通配符

符號 意義
* 0到無窮多個任意字符
? 一個任意字符
[] 一個[]內的字符(非任意字符). 例如, [abcd], a,b,c,d中的任意一個字符
[-] 編碼順序內的字符. 例如, [0-9]表明0到9之間的全部數字
[^] 反向選擇. 例如, 1非a,b,c外的其餘的任意一個字符

文件搜索

VPATH(大寫)變量指定搜索目錄

make默認在當前目錄搜索文件, 而後再到VPATH指定的目錄去搜索.

VPATH = src:../headers

上面的定義指定兩個目錄,, 用:分割, "src"和"../headers", make按照這個順序進行搜索, 固然, 當前目錄是最高優先級.

vpath(小寫)關鍵字設定搜索規則和路徑

三種使用方法

  • vpath <pattern> <directories>
    爲符合模式<patern>的文件指定搜索目錄<directories>

  • vpath <pattern>
    清楚設置的符合模式<pattern>的文件的搜索目錄

  • vpath
    清楚全部已被設置好的文件的搜索目錄

vpath使用的<pattern>中須要包含%字符, 表示匹配零或者若干字符

vpath %c foo:bar
vpath %c usr
vpath % blish

上面的語句表示.c結尾的文件, 依次搜索"foo", "bar", "user", "blish"目錄

條件判斷

ifeq 條件語句開始, else條件表達式爲假, endif表示一個條件語句的結束.

  • ifeq, 比較參數arg1和arg2是否相同,相同則爲真

ifeq '<arg1>' '<arg2>'
ifeq "<arg1>" "<arg2>"
ifeq '<arg1>' "<arg2>"
ifeq "<arg1>" '<arg2>'
  • 'ifneq`是否相同, 不一樣則爲真

  • ifdef <variable-name>判斷變量的值非空, 則爲真.只是測量變量是否有值, 並不會把變量擴展到當前位置

函數

函數調用以$開頭, 以圓括號或花括號把函數名和參數括起.參數以,分隔, 函數名和參數之間以空格分隔;

$(<function> <arguments1,arguments2>) #小括號可換爲大括號

經常使用的字符串處理函數

  • $(subst <from>,<to>,<text>)
    把子串<text>中的<from>字符串替換爲<to>, 返回替換後的子串

  • (strip <string>)
    去掉<string>子串中開頭和結尾的空字符,返回被去掉空格的字符串

  • (findstring <find>,<in>)
    查找字符串函數, 在子串<in>中查找<find>子串, 若是找到, 返回<find>, 不然返回空字符串

  • $(word <n>,<text>)
    取單詞函數, 取字符串<text>中的第<n>的單詞, 從1開始.返回子串<text>中的第<n>個單詞. 若是<n>比<text>中的單詞要大, 返回空字符串

  • $(wordlist <s>,<e>,<text>)
    取字符串函數
    從字符串<text>中取<s>開始到<e>的單詞串, <s>和<e>是一個數字

特定字符

-放在命令前, 不管出現什麼錯誤, 繼續執行

註釋用#字符

命令以[Tab]鍵開始

\換行符, 相似c語言, 表示鏈接上一行

Makefile與vim

vim內置了autocmd, 因此可使用:make, make當前目錄:pwd下的Makefile

:make           #執行當前目錄下的Makefile

Use the following commands to examine the compile errors with vim

:copen          #open a mini-window with list of errors, hit enter on an error to jump to line
:cclose         #close the mini-window
:cn[ext]          #jump to the next errror
:cp[revious]

具體用法, 能夠在vim下:h copen:h cnext

Makefile經驗總結

  • 整個Makefile文件都不要使用空格鍵最爲安全,你看到的全部空格實際上是有Tab鍵產生的,一旦使用了空格鍵,文件是默認空格是編譯語言的其中一部分,從而會致使錯誤的出現。包括在編寫註釋的時候,也不要用空格

  • 使用-l鏈接庫模塊時,不要直接寫文件名,要把文件名中開頭的lib去掉。例如,源文件是libopencv_core.so,在鏈接時使用-lopencv_core.

  • 多個鏈接模塊,使用空格分開。

參考: 陳皓的Makefile教程


  1. abc
相關文章
相關標籤/搜索