主頁 > 作業系統 > Makefile常用的函式

Makefile常用的函式

2020-12-31 06:15:17 作業系統

Makefile定義了一系列的規則來指定專案中哪些源檔案需要先編譯,哪些檔案后編譯,哪些檔案需要重新編譯,甚至更復雜的操作,一旦寫好,只需要一個make命令,整個工程按照Makefile中寫好的規則自動完成編譯,這樣極大的提高了軟體開發效率,寫好的Makefile檔案是被make解釋器決議的,make決議器除了決議Makefile檔案中編譯規則外,還提供了一些特定功能的函式,這些函式可以在撰寫Makefile中直接使用,掌握其中的一些常用函式,有助于我們更好撰寫Makefile來管理我們的工程,

一、函式的呼叫語法

在正式介紹這些函式的詳細功能前,我們先來看下Makefile中函式的呼叫語法,函式的呼叫其實和變數的使用差不多,也是使用“$”符號來標識的,其語法如下:

$(<function> <arguments>)

 或者是

${<function> <arguments>}

其中 function 代表函式名稱,arguments 代表函式引數,函式名和引數之間是以“空格”分割開的,一個函式可能有多個引數,不同的引數之間通過“逗號”來分割開,

下面來通過一個例子,來看函式是怎么呼叫的

DIR = D:\MinGW\mingw64\bin
DIR_N = $(subst \, /, $(DIR))

上面第二條陳述句$(subst \, /, $(DIR))就是對函式的呼叫,subst是函式名, 后面‘\’, ‘/’,‘$(DIR)’代表是傳給這個函式的三個引數,$(DIR)代表使用DIR這個變數,好了,我們已經對函式的呼叫格式做了簡單介紹,至于subst這個函式的功能,我們在后面內容中會進行詳細解釋,

二、常用函式介紹

根據功能劃分,可以將Makefile中函式分為不同的型別,下面根據功能進行分類,對Makefile中的常用函式進行介紹

1、字串處理函式

  • subst函式

subst是一個字串替換函式,函式使用格式如下:

$(subst <from>,<to>,<text>)

<from> 是被替換字串,<to> 是替換字串,<text> 是替換操作作用的字串,函式回傳的結果是替換完成后的字串,

示例:

DIR = D:\MinGW\mingw64\bin
DIR_N = $(subst \, /, $(DIR))
all:
  @echo $(DIR)
  @echo $(DIR_N)

使用subst函式,將DIR變數表示的字串里的‘\’替換成‘/’,替換結果賦值給 DIR_N 變數,執行之后,DIR_N 變數內容為“D:/MinGW/mingw64/bin”

  • patsubst函式

patsubst也是一個字串替換函式,與subst函式不同的是它是以模式進行匹配替換的,函式使用格式如下:

$(patsubst <pattern>,<replacement>,<text>)

patsubst函式查找字串中以空格分開的單詞,是否符合模式部分,如果匹配的話,則將其替換成指定內容,<pattern> 是被替換模式,<replacement> 是替換形式,<text> 是替換操作作用的字串,函式回傳的結果是替換完成后的字串,

示例:

SRC_FILE = main.c bsp_led.c bsp_uart.c
OBJ_FILE = $(patsubst %.c, %.o, $(SRC_FILE))
all:
  @echo $(SRC_FILE)
  @echo $(OBJ_FILE)

通配符“%”,表示通配任意長度的字串,$(patsubst %.c, %.o, $(SRC_FILE))即將SRC_FILE中所有的以.c為后綴的單詞替換成以.o為后綴,執行之后,OBJ_FILE變數內容為“main.o bsp_led.o bsp_uart.o

(注:%默認情況下被轉義,如果想匹配字串中'%'字符,可以用“\”來轉義,“\%”來表示真實含義的“%”字符)

  • strip函式

strip是一個去除空格函式,函式的使用格式如下:

$(strip <text>)

strip函式去掉字串的開頭和結尾的空格字串,并且將其中的多個連續的空格合并成為一個空格,<text>表示被操作的字串,函式回傳值為去掉空格后的字串

示例:

obj_space = Hello     World      !
obj = $(strip $(obj_space))
all:
  @echo $(obj_space)
  @echo $(obj)

將obj_space變數中多個連續的空格合并成為一個空格,結果賦值給obj變數,obj變數內容為“Hello World!”

  • findstring函式

findstring是一個查找字串函式,函式的使用格式如下:

$(findstring <find>,<in>)

findstring函式有兩個引數,<find> 表示目標字串,<in> 表示源字串,如果在源字串中查找到目標字串,就回傳目標字串,否則回傳空

示例:

src_obj = Hello Makefile
find_obj = $(findstring Makefile, $(src_obj))
all:
    @echo $(find_obj)

src_obj變數中有“Makefile”字串,所以回傳結果是“Makefile”,find_obj變數內容為“Makefile”

  • filter函式

filter函式是一個過濾函式,函式的使用格式如下:

$(filter <pattern>,<text>)

filter函式有兩個引數,<pattern> 傳入的是過濾的模式,<text> 傳入的是源字串,函式過濾出text中符合pattern模式(可以有多個pattern)的字串,函式回傳值為過濾出的字串,

示例:

SRC_FILE = main.c led.c readme.txt start.S
OBJ_FILE = $(filter %.c %.S, $(SRC_FILE))
all:
    @echo $(OBJ_FILE)

從SRC_FILE變數中過濾出所有的.c檔案和所有的.S檔案,過濾的結果賦值給變數OBJ_FILE,SRC_FILE變數中.c檔案有main.c 、led.c,.S檔案有start.S,所以使用filter函式過濾之后OBJ_FILE變數內容“main.c led.c start.S”

(注:還有個和filter函式功能相反的函式——filter-out,兩個函式引數一致,filter-out是過濾掉<text>中符合<pattern>的內容,回傳剩下的內容,如:上例中filter換成filter-out,執行結果為“readme.txt”)

2、檔案名操作函式

  • wildcard函式

wildcard函式獲取滿足匹配模式的檔案名,函式的使用格式如下:

$(wildcard PATTERN)

wildcard函式列出當前目錄下所有符合PATTERN格式(可以有多個pattern)的檔案名,回傳值為當前檔案夾下所有符合模式 PATTERN 的檔案名,回傳的字串中各檔案名之間使用空格分隔,

示例:

OBJS = $(wildcard %.c)
all:
    @echo $(OBJS)
  • dir函式

dir函式是一個獲取目錄函式,使用格式如下:

$(dir <names>)

dir函式從檔案名序列<names>中取出目錄部分,如果<names>中沒有 "/",取出的值為"./" (當前目錄),回傳值為目錄部分,指的是最后一個反斜杠之前的部分,如果沒有反斜杠將回傳“./”,

示例:

OBJS = driver/led.c mmt
all:
  @echo $(dir $(OBJS))

取出OBJS變數內容的目錄部分,執行結果為“driver/ ./”

  • notdir函式

notdir函式和dir函式功能剛好相反,函式使用格式如下:

$(notdir <names>)

notdir函式的功能是從檔案名序列<names>中取出非目錄的部分,非目錄的部分是最后一個反斜杠之后的部分,回傳值為檔案非目錄的部分,

示例:

OBJS = driver/led.c mmt
all:
  @echo $(notdir $(OBJS))

取出OBJS變數內容的非目錄部分,執行結果為“led.c nmt”

  • suffix函式

獲取后綴名函式,函式使用格式如下:

$(suffix <names>)

suffix函式從檔案名序列<names>中取出各個檔案的后綴名,回傳值為檔案名序列<names>中的后綴序列,如果檔案沒有后綴名,則回傳空字串,

示例:

OBJS = driver/led.c mmt
all:
  @echo $(suffix $(OBJS))

取出OBJS變數內容中的各檔案后綴名,執行結果為“.c”

  • basename函式

獲取前綴函式,函式使用格式如下: 

$(basename <names>)

basename函式是從檔案名序列<names>中取出各個檔案名的前綴部分,回傳值為被取出來的檔案的前綴名,如果檔案沒有前綴名則回傳空的字串,

示例:

OBJS = driver/led.c mmt
all:
  @echo $(basename $(OBJS))

取出OBJS變數內容中的各檔案前綴名,執行結果為“driver/led mmt”

  • addsuffix函式

添加后綴函式,函式使用格式如下:

$(addsuffix <suffix>,<names>)

addsuffix函式是把后綴<suffix>添加到<names>中的每個單詞后面,回傳值為添加上后綴的檔案名序列,

示例:

OBJS = driver/led mmt
all:
  @echo $(addsuffix .c, $(OBJS))

給OBJS變數內容中的各單詞添加后綴名,執行結果為“driver/led.c mmt.c”

  • addprefix

添加前綴函式,函式使用格式如下:

$(addperfix <prefix>,<names>)

addprefi函式是把前綴prefix加到names中的每個單詞的前面,回傳值為添加上前綴的檔案名序列,

示例:

OBJS = led.c uart
all:
  @echo $(addprefix driver/, $(OBJS))

給OBJS變數內容中的各單詞添加前綴driver/,執行結果為“driver/led.c 、driver/uart”

3、回圈、選擇函式

  • foreach函式

回圈函式,函式使用格式如下:

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

把引數<list>中的單詞逐一取出放到引數<var>所指定的變數中,然后在執行<text>所包含的運算式,每一次<text>會回傳一個字串,回圈程序中,<text>所回傳的每個字串會以空格分割,最后當整個回圈結束的時候,<text>所回傳的每個字串所組成的整個字串(以空格分隔)將會是foreach函式的回傳值,

示例:

src = https://www.cnblogs.com/053179hu/p/$(wildcard *.c)

objs:=$(foreach var, $(basename $(src)), $(var).o)
all:
    @echo $(objs)

先使用wildcard函式獲取當前檔案夾下所有的.c檔案名,然后呼叫foreach函式將保留存在當前檔案名的字串中每個.c單詞換成.o

  • if函式

選擇結構函式,函式使用格式如下:

$(if <condition>,<then-part>)或(if<condition>,<then-part>,<else-part>)

if函式可以包含else部分,也可以不包含else部分,即if函式的引數可以是兩個,也可以是三個,如果<condition>部分回傳的是非空字串,那么if條件成立,<then-part>部分被執行,否則<else-part>被執行,

示例:

OBJ = app.c
OBJ = $(if $(OBJ),$(OBJ),main.c)
all:
      @echo $(OBJ)

OBJ變數為非空字串,if條件成立,回傳的是OBJ變數內容,OBJ變數被回傳,OBJ變數仍為app.c

三、總結

這里介紹了一些Makefile中常用的函式,通過例子演示,展示了這些函式是如何使用的,Makefile中還有一些其它的函式可供我們去使用,后續接觸到時再對本文的內容進行補充!

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/242656.html

標籤:嵌入式

上一篇:Linux內核中斷頂半部和底半部的理解

下一篇:Linux學習筆記:(一)常用命令大全

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more