Makfile總結

2022-09-28 12:00:26

Makfile總結

在前面的三篇文章徹底掌握Makefile(一)徹底掌握Makefile(二)徹底掌握Makeifle(三)當中我們仔細介紹了Makefile各種使用方法,在本篇文章當中主要是對前面三篇關於makefile的文章做一個總結,方便大家快速查閱和檢查。

Makefile基礎以及小技巧

Make命令的工作流程

當我們在命令列當中輸入make的時候他的執行流程如下:

  • make命令首先會在當前目錄下面尋找makefile或者Makefile檔案。
  • 尋找到makefile檔案之後,他會在檔案當中尋找到一個編譯目標,比如在上面的makefile檔案當中他會找到demo這個編譯目標,而不是clean這個目標,因為clean是第二個編譯目標。
  • 然後make會解析編譯目標的依賴,如果這個依賴是其他的編譯目標A的話,那麼make會先完成它依賴的編譯目標A的命令,如果它依賴的編譯目標A也存在依賴B的話,make就會去執行依賴的B的編譯命令,如此的遞迴下去,知道有所得依賴目標都存在了,才會完成第一個編譯目標的編譯,這個也很好理解,只有依賴檔案都存在了我們才能夠完成正確的編譯過程。

Makefile當中的小技巧

  • makefile基本規則
編譯目標:依賴檔案
	編譯命令
  • 一個最基本的makefile
main: demo.o myprint.o
	gcc demo.o myprint.o -o out
	echo make 解析編譯完成

demo.o: demo.c 
	gcc -c demo.c -o demo.o

myprint.o: myprint.c 
	gcc -c myprint.c -o myprint.o

clean:
	rm myprint.o demo.o out
  • 在makefile當中使用變數
cflags=-c
main: demo.o myprint.o
	gcc demo.o myprint.o -o out

demo.o: demo.c 
	gcc $(cflags) demo.c -o demo.o

myprint.o: myprint.c 
	gcc $(cflags) myprint.c -o myprint.o

clean:
	rm myprint.o demo.o out
  • 在makefile當中使用include
include submakefile

demo.o: demo.c 
	gcc $(cflags) demo.c -o demo.o

myprint.o: myprint.c 
	gcc $(cflags) myprint.c -o myprint.o

clean:
	rm myprint.o demo.o out
  • 在makefile當中使用PHONY
cflags=-c
main: demo.o myprint.o
	gcc demo.o myprint.o -o main

demo.o: demo.c 
	gcc $(cflags) demo.c -o demo.o

myprint.o: myprint.c 
	gcc $(cflags) myprint.c -o myprint.o

clean:
	rm myprint.o demo.o main
.PHONY: clean # 增加這一行
  • 在makefile當中使用萬用字元
cflags=-c

main: demo.o myprint.o
	gcc demo.o myprint.o -o main

%.o: %.c 
	gcc $(cflags) $<
clean:
	rm myprint.o demo.o main
.PHONY: clean
  • 在makefile當中使用VPATH自動搜尋
cflags=-c

VPATH=./files

main: demo.o myprint.o a.o b.o
	gcc demo.o myprint.o a.o b.o -o main

demo.o:demo.c
	gcc $(cflags) demo.c 

myprint.o:myprint.c
	gcc $(cflags) myprint.c 

a.o: a.c
	gcc $(cflags) $<
b.o: b.c 
	gcc $(cflags) $<

clean:
	rm myprint.o demo.o main
.PHONY: clean
  • @符號

有時候在makefile當中我們不想輸出某些命令(如果不進行設定makefile會輸出每一條我們執行過的命令),我們就可以使用@符號進行修飾。

main: demo.c
	@echo hello world
  • override覆蓋命令列的賦值,讓makefile檔案當中的變數覆蓋命令列當中的變數。

Makefile當中進行if判斷

ifeq 和 ifneq

主要是用於判斷字元是否相等。

cc=g++

main: demo.c
	echo $(cc)

ifeq ($(cc), gcc)
	echo $(cc) = 相等的語句執行了
else
	echo $(cc) != 不相等的語句執行了
endif
cc=g++

main: demo.c
	echo $(cc)

ifneq ($(cc), gcc)
	echo $(cc) != gcc
else
	echo $(cc) = gcc
endif

ifdef 和 ifndef

判斷變數是否被定義或者為空

foo = 1
main: demo.c
	echo demo
ifdef foo
	echo define foo
else
	echo not define foo
endif
main: demo.c
	echo demo
ifdef foo
	echo define foo
else
	echo not define foo
endif

Makefile當中的函數

在makefile當中除了能夠使用條件表示式之外我們還可以使用函數,在makefile當中函數的使用規則如下:

$(<函數名> <函數引數>)
或者
將()替換為{}

函數的呼叫規則如上圖所示,函數引數用.隔開。

字串函數

subst

$(subst <from>,<to>,<text>)
  • 字串替換函數。
  • 表示文字,這個函數會將text當中是的字串替換為
s = ii am learning makefile
ss = $(subst ii, you, $(s))

main: demo.c
	echo demo
	echo $(s)
	echo $(ss)

patsubst

$(patsubst <pattern>,<replacement>,<text>)
  • pattern 表示第一個引數,用於表示如何對 text 進行匹配。
  • replacement 表示第二個引數 表示如何對匹配的字元進行重寫。
  • patsubst在進行匹配替換的時候,會先將字串text根據空格或者tab鍵或者回車換行符進行分割,然後一一的進行替換和匹配。
s = a.c b.c d.c abc.c abo.c
ss = $(patsubst %.c, %.o, $(s))

main: demo.c
	echo demo
	echo $(s)
	echo $(ss)

Strip

$(strip <string>)

主要功能去掉字串 string 首尾的空格。

findstring

$(findstring <find>,<text>)

這個函數的作用是從字串當中尋找字串,如果找到了字串就返回字串,否則返回空。

filter

$(filter <pattern...>,<text>)

這是一個過濾函數,這個函數執行時,首先會根據空格或者tab鍵或者回車換行符進行分割,然後一一的進行filter函數的操作。然後遍歷每一個被分割出來的字元,如果不滿足pattern的規則的話對應的字元就會被過濾掉。

s = a.c abo.c s.o s.y x.o x.y
ss = $(filter %.c %.o, $(s))

main: demo.c
	echo $(ss)

filter-out

這個函數和filter的用法是一樣的只不過,作用剛好相反,filter是儲存符合條件的字串,filter-out是儲存不符合條件的字串。

s = a.c abo.c s.o s.y x.o x.y
ss = $(filter-out %.c %.o, $(s))

main: demo.c
	echo $(ss)

sort

這個函數主要是用於幫助字串排序的,同時還會取出分割之後相同的字串。

s = g a b c d e f  a a a a 
ss = $(sort $(s))

main: demo.c
	echo $(ss)

word

$(word <n>,<text>)

這個功能很簡單,返回當中第個字元。

s = g a b c d e f  a a a a 
ss = $(word 1, $(s)) # 取出第一個字元

main: demo.c
	echo $(ss)

wordlist

$(wordlist <start>,<end>,<text>)

這個也是從字串當中取出字元,是取出第個字元一直到第個字元。

s = g a b c d e f  a a a a 
ss = $(wordlist 1, 5, $(s))

main: demo.c
	echo $(ss)

words

統計單詞的個數。

s = 1 2 3 4 5
ss = $(words $(s))

main: demo.c
	echo $(ss)

firstword

這個函數主要是用於返回第一個字串的。

s = 1 2 3 4 5
ss = $(firstword $(s))

main: demo.c
	echo $(ss)

檔案函數

dir與notdir函數

dir函數主要書獲取檔案路徑當中的目錄部分,而notdir函數主要是獲取檔案路徑當中檔名的部分

file = ./files/a.c
fdir = $(dir $(file))
nfdir = $(notdir $(file))

main: demo.c
	echo $(fdir)
	echo $(nfdir)

suffix函數

這個函數主要是用於獲取檔案的字尾名。

file = ./files/a.c
fdir = $(dir $(file))
nfdir = $(notdir $(file))
name = $(suffix $(file))
main: demo.c
	echo $(fdir)
	echo $(nfdir)
	echo $(name)

basename

這個函數用於獲取檔案路徑當中除去字尾名的部分。

file = ./files/a.c
base = $(basename $(file))
main: demo.c
	echo $(base)

addsuffix

這個函數主要是給檔案加上字尾的。

file = ./files/a.c
base = $(addsuffix .c, $(file))
main: demo.c
	echo $(base)

addprefix

這個函數的主要作用就是在字串的前面加上一串字元。

file = files/a.c
base = $(addprefix ./src/main/, $(file))
main: demo.c
	echo $(base)

其他函數

迴圈函數foreach

foreach函數的主要使用規則為:

$(foreach <var>,<list>,<text>)

我們直接使用一個例子來說明這個情況:

files = a.c b.c c.c d.c
new_files = $(foreach n, $(files), $(n)pp)
main: demo.c
	echo $(new_files)

call函數

call函數在makefile當中可以用於呼叫我們自定義的一個表示式,他的語法個數如下面所示:

$(call <expression>,<parm1>,<parm2>,...,<parmn>)
  • 表示定義的表示式的名字。
  • 表示第n個引數,我們在當中可以使用$(n)進行參照。
a=a.c
b=b.c
c=$(a)-------$(b)
main: demo.c
	echo $(c)

在makefile當中使用shell函數

我們在makefile的表示式當中可以使用shell的函數。

比如現在我們有一個檔案叫做test.txt,檔案的內容如下所示:

a.c b.c c.c d.c
content=$(shell cat test.txt) # 將shell命令的輸出內容賦給content

main: demo.c
	echo $(content) # 輸出content

origin函數

origin這個函數主要是返回變數的定義方式,使用格式如下:

$(origin <variable>) # 其中 variable 是變數名字 這裡不需要使用 $ 符號去參照

error函數

在makefile當中我們可以使用error函數讓makefie停止執行。當我們有需求:讓在某種條件下讓makefile停止編譯

data=data

ifeq ($(data), data)
$(error "data == data")
endif

main: main.c
	gcc main.c

除此之外還有個warning函數使用方法和error一樣!

總結

在本篇文章當中主要給大家總結了一些常見的makefile的使用方法,方便大家查閱複習!


以上就是本篇文章的所有內容了,我是LeHung,我們下期再見!!!更多精彩內容合集可存取專案:https://github.com/Chang-LeHung/CSCore

關注公眾號:一無是處的研究僧,瞭解更多計算機(Java、Python、計算機系統基礎、演演算法與資料結構)知識。