1. 程式人生 > >從頭開始寫專案Makefile(十):make內嵌函式及make命令顯示

從頭開始寫專案Makefile(十):make內嵌函式及make命令顯示

   【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】
    這一節我們講一下make的函式,在之前的章節已經講到了幾個函式:wildcard、patsubst、notdir、shell等。一般函式的呼叫格式如下:
$(funcname arguments)

$(funcname arguments)
其中funcname是需要呼叫函式的函式名稱,應該是make內嵌函式;arguments是函式引數,引數和函式名之間使用空格分割,如果存在多個引數時,引數之間使用逗號“,”分開。函式呼叫以“$”開頭,使用成對的圓括號或花括號把函式名和引數括起,一般使用圓括號。
下面來看一下常用的一些函式:
1.    獲取匹配模式檔名函式—wildcard 。
用法:$(wildcard PATTERN)
該函式會列出當前目錄下所有符合模式“PATTERN”格式的檔名。返回空格分割的、存在當前目錄下的所有符合模式“PATTERN”的檔名。
例如:
SRC_FILES = $(wildcard src/*.c)
返回src目錄下所有.c檔案列表。
2.    字串替換函式—subst。
用法:$(subst FROM,TO,TEXT)
該函式把字串“TEXT”中的“FROM”字元替換為“TO”,返回替換後的新字串。
3.    模式替換函式—patsubst。
用法:$(patsubst PATTERN,REPLACEMENT,TEXT)
該函式搜尋“TEXT”中以空格分開的單詞,將符合模式“TATTERN”替換為“REPLACEMENT” 。引數“PATTERN”中可以使用模式萬用字元“%”,來代表一個單詞中的若干字元。如果引數“REPLACEMENT”中也包含一個“%” ,那麼“REPLACEMENT”中的“%”將是“TATTERN”中的那個“%”所代表的字串。
例如:
SRC_OBJ = $(patsubst %.c, %.o, $(SRC_FILES))
將SRC_FILES中所有.c檔案替換為.o返回給變數SRC_OBJ。
此函式功能類似之前講過的變數替換,http://blog.csdn.net/shallnet/article/details/37529935
變數替換格式是“$(var:a=b)”或“${var:a=b}”,其意思是,把變數“var”中所有以“a”字串“結尾”的“a”替換成“b”字串。
例如我們存在一個代表所有.c 檔案的變數。定義為“src_files = a.c b.c c.c” 。
為了得到這些.c檔案所對應的.o原始檔。如下兩種使用可以得到同一種結果::
$(objects:.c=.o)
$(patsubst %.c,%.o,$( src_files))
4.    過濾函式—filter。
用法:$(filter PATTERN…,TEXT)
該函式過濾掉字串“TEXT”中所有不符合模式“PATTERN”的單詞,保留所有符合此模式的單詞。可以使用多個模式。模式中一般需要包含模式字元“%” 。存在多個模式時,模式表示式之間使用空格分割。返回空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
5.    反過濾函式—filter-out。
用法:$(filter-out PATTERN...,TEXT)
和“filter”函式實現的功能相反。過濾掉字串“TEXT”中所有符合模式“PATTERN” 的單詞, 保留所有不符合此模式的單詞。 可以有多個模式。存在多個模式時,模式表示式之間使用空格分割。
6.    取目錄函式—dir。
用法:$(dir NAMES…)
從檔名序列“NAMES…”中取出各個檔名的目錄部分。檔名的目錄部分就是包含在檔名中的最後一個斜線( “/” ) (包括斜線)之前的部分。返回空格分割的檔名序列“NAMES…”中每一個檔案的目錄部分。如果檔名中沒有斜線,認為此檔案為當前目錄( “./” )下的檔案。
7.    取檔名函式——notdir。
用法:$(notdir NAMES…)
從檔名序列“NAMES…”中取出非目錄部分。目錄部分是指最後一個斜線( “/” ) (包括斜線)之前的部分。刪除所有檔名中的目錄部分,只保留非目錄部分。檔名序列“NAMES…”中每一個檔案的非目錄部分。
8.    取字尾函式—suffix。
用法:$(suffix NAMES…)
函式從檔名序列“NAMES…”中取出各個檔名的字尾。字尾是檔名中最後一個以點“.”開始的(包含點號)部分,如果檔名中不包含一個點號,則為空。 返回以空格分割的檔名序列“NAMES…”中每一個檔案的字尾序列。
9.    取字首函式—basename。
用法:$(basename NAMES…)
從檔名序列“NAMES…”中取出各個檔名的字首部分(點號之後的部分) 。字首部分指的是檔名中最後一個點號之前的部分。 返回空格分割的檔名序列“NAMES…”中各個檔案的字首序列。如果檔案沒有字首,則返回空字串。

    這裡僅僅講到一些常用的函式,還有一些函式沒有講到,用到的時候可以去翻翻makefile手冊。

    通常情況下make在編譯時會打印出當前正在執行的命令,當編譯連結選項很長時,會輸出很多東西在螢幕上,如果我 不想再螢幕上看到很多東西,我們可以在命令前面加上@,這樣命令就不會輸出到螢幕了。我們這樣嘗試修改下:
# make
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/ipc'
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/ipc'
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/tools'
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/tools'
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/main'
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/main'
# 
發現只有進入目錄和退出目錄的顯示,這樣很難知道目前編譯過程。其實我們可以在規則命令處加入一行類似列印:
@echo "do something......"
這樣可以輸出目前正在做的事,又不會輸出正在執行命令。現在將規則修改下如下:
$(OBJDIR) :
>[email protected] "   MKDIR $(notdir [email protected])..."
>[email protected] -p [email protected]

ifneq ($(SRC_BIN),)
$(BINDIR)/$(SRC_BIN) : $(SRC_OBJ)
>[email protected] "   LINK $(notdir [email protected])..."
>[email protected]$(CC) -o [email protected] $^ $(LDFLAGS)
endif

ifneq ($(SRC_LIB),)
$(LIBDIR)/$(SRC_LIB) : $(SRC_OBJ)
>[email protected] "    ARCHIVE $(notdir [email protected])..."
>[email protected]$(AR) rcs [email protected] $^
>[email protected] "    COPY [email protected] to $(SRC_BASE)/libs"
>[email protected] [email protected] $(SRC_BASE)/libs
endif

$(SRC_OBJ) : $(OBJDIR)/%.o : %.c
>[email protected] "    COMPILE $(notdir $<)..."
>[email protected]$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o [email protected]


編譯輸出如下:
# make
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/ipc'
    COMPILE ipc.c...
    ARCHIVE libipc.a...
    COPY ../../build/unix_dbg/lib/libipc.a to ../../libs
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/ipc'
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/tools'
    COMPILE base64.c...
    COMPILE md5.c...
    COMPILE tools.c...
    ARCHIVE libtools.a...
    COPY ../../build/unix_dbg/lib/libtools.a to ../../libs
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/tools'
make[1]: Entering directory `/home/Myprojects/example_make/version-3.1/src/main'
    COMPILE main.c...
   LINK target_bin...
make[1]: Leaving directory `/home/Myprojects/example_make/version-3.1/src/main'
#


其中目錄切換的輸出仍然很多,我們可以將其關閉,這需要使用到make的引數,在make -C是指定--no-print-
directory引數。我們將頂層目錄下Makefile規則修改如下:
$(BUILDDIR):
>[email protected] "    Create directory [email protected] ..."
>---mkdir -p $(BUILDDIR)/bin $(BUILDDIR)/lib

$(MODULES):
>[email protected]$(MAKE) -C $(DIR)/[email protected] [email protected] --no-print-directory

main:tools ipc

clean :
>[email protected] subdir in $(MODULES); \
>---do $(MAKE) -C $(DIR)/$$subdir MODULE=$$subdir [email protected] --no-print-directory; \
>---done
編譯輸出:
# make
    COMPILE ipc.c...
    ARCHIVE libipc.a...
    COPY ../../build/unix_dbg/lib/libipc.a to ../../libs
    COMPILE base64.c...
    COMPILE md5.c...
    COMPILE tools.c...
    ARCHIVE libtools.a...
    COPY ../../build/unix_dbg/lib/libtools.a to ../../libs
    COMPILE main.c...
   LINK target_bin...
# make clean
rm -f  ../../build/unix_dbg/obj/ipc/ipc.o ../../build/unix_dbg/lib/libipc.a
rm -f  ../../build/unix_dbg/obj/main/main.o ../../build/unix_dbg/bin/target_bin
rm -f  ../../build/unix_dbg/obj/tools/base64.o  ../../build/unix_dbg/obj/tools/md5.o   
../../build/unix_dbg/obj/tools/tools.o ../../build/unix_dbg/lib/libtools.a

#

這樣看上去輸出清爽多了。其實我們也可以使用make -s 來全面禁止命令的顯示。



相關推薦

從頭開始專案Makefilemake函式make命令顯示

   【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】     這一節我們講一下make的函式,在之前的章節已經講到了幾個函式:wildcard、patsubst、notdir、shell

從頭開始專案Makefile引數傳遞、條件判斷、include

在多個Makefile巢狀呼叫時,有時我們需要傳遞一些引數給下一層Makefile。比如我們在頂層Makefile裡面定義的開啟除錯資訊變數DEBUG_SYMBOLS,我們希望在進入子目錄執行子Makefile時該變數仍然有效,這是需要將該變數傳遞給子Makefile,那怎麼傳遞呢?這裡有兩種方法:

從頭開始專案Makefile巢狀執行(轉)

【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】 在大一些的專案裡面,所有原始碼不會只放在同一個目錄,一般各個功能模組的原始碼都是分開的,各自放在各自目錄下,並且標頭檔案

從頭開始專案Makefile基本規則

【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】 一般一個稍大的linux專案會有很多個原始檔組成,最終的可執行程式也是由這許多個原始檔編譯連結而成的。編譯是把一個.c或.cpp檔案編譯成

從頭開始專案Makefile模式規則

【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】     上一節講到目錄建立成功,目標檔案沒有生產到對應目錄下,這裡我們先給目標檔案加上對應目錄,這樣的話產生對應的目標檔案會直接生成到對應

[Golang] 從零開始Socket Server3 對長、短連接的處理策略模擬心跳

microsoft ted 每次 range 點擊 關閉 ade 而在 href 通過前兩章,我們成功是寫出了一套湊合能用的Server和Client,並在二者之間實現了通過協議交流。這麽一來,一個簡易的socket通訊框架已經初具雛形了,那麽我們接下來做的

[Golang] 從零開始Socket Server5Server的解耦—通過Router+Controller實現邏輯分發

       在實際的系統專案工程中中,我們在寫程式碼的時候要儘量避免不必要的耦合,否則你以後在更新和維護程式碼的時候會發現如同深陷泥潭,隨便改點東西整個系統都要變動的酸爽會讓你深切後悔自己當初為什麼非要把東西都寫到一塊去(我不會說我剛實習的時候就是這麼幹

[Golang] 從零開始Socket Server4將執行引數放入配置檔案XML/YAML

    為了將我們寫好的Server釋出到伺服器上,就要將我們的程式碼進行build打包,這樣如果以後想要修改一些程式碼的話,需要重新給程式碼進行編譯打包並上傳到伺服器上。     顯然,這麼做過於繁瑣。。。因此常見的做法都是將Server執行中

[Golang] 從零開始Socket Server2 自定義通訊協議

        在上一章我們做出來一個最基礎的demo後,已經可以初步實現Server和Client之間的資訊交流了~ 這一章我會介紹一下怎麼在Server和Client之間實現一個簡單的通訊協議,從而增強整個資訊交流過程的穩定性。  

[Golang] 從零開始Socket Server1 Socket-Client框架

第一次跑到網際網路公司實習 。。感覺自己進步飛快啊~第一週剛寫了個HTTP伺服器用於微信公共號的點餐系統~ 第二週就直接開始一邊自學GO語言一邊寫用於Socket的伺服器了。。。 因為發現Golang這一塊資料挺少的,接下來我會在Blog裡把整個Server的Coding,還有遇到的坑都記錄

[Golang] 從零開始Socket Server3 對長、短連線的處理策略模擬心跳

    通過前兩章,我們成功是寫出了一套湊合能用的Server和Client,並在二者之間實現了通過協議交流。這麼一來,一個簡易的socket通訊框架已經初具雛形了,那麼我們接下來做的,就是想辦法讓這

從零一個編譯器編譯前傳之直接解釋執行

專案的完整程式碼在 C2j-Compiler 前言 這一篇不看也不會影響後面程式碼生成部分 現在經過詞法分析語法分析語義分析,終於可以進入最核心的部分了。前面那部分可以稱作編譯器的前端,程式碼生成程式碼優化都是屬於編譯器後端,如今有關編譯器的工作崗位主要都是對後端的研究。當然現在寫的這個編譯器因為水平有限

SDL入門教程2、直接通過Unicode讓SDL顯示中文

作者:龍飛2.1:SDL本身可以顯示中文嗎?        SDL的擴充套件庫SDL_ttf本身具備顯示中文的功能嗎?網上很多觀點,說不能顯示的,甚至做了分析解釋了原因。但是,事實是,SDL本身就可以顯示中文。如果我們看看SDL_ttf.c的原始碼,我們可以看到,最終用於構建

跟我一起 Makefile

四、foreach 函式   foreach函式和別的函式非常的不一樣。因為這個函式是用來做迴圈用的,Makefile中的foreach函式幾乎是仿照於Unix標準Shell(/bin/sh)中的for語句,或是C-Shell(/bin/csh)中的foreach語句而構建的。它的語法是: &

[Golang] 從零開始Socket Server6【完結】日誌模組的設計與定時任務模組模組

好久沒寫文章啦。。。今天把golang挖的這個坑給補完吧~ 作為一個Server,日誌(Log)功能是必不可少的,一個設計良好的日誌模組,不論是開發Server時的除錯,還是執行時候的維護,都是非常有幫助的。 因為這裡寫的是一個比較簡化的Server框架,因此我選擇對Golang本

從零開始Vue專案實戰-專案結構

現在在瀏覽器中輸入http://localhost:8083,可以看到初始的“Welcome to Your Vue.js App”頁面了 目錄結構 ├── README.md 專案介紹 ├── index.html 入口頁面 ├── build

從零開始Vue專案實戰-搭建環境

1、下載node.js並安裝 下載地址:https://nodejs.org/en/download/。 下載.msi 格式的直接連續下一步就可以了。安裝完成後可以用 node -v 和 npm -v 檢視版本號。 2、安裝vue-cli 腳手架構建工具 在命令列中輸入npm ins

從零開始Vue專案實戰-準備篇

從前參與過一個react專案的程式碼編寫,大神搭建的框架,我主要負責業務邏輯程式碼編寫,現在回想起來似乎又什麼都不會,現在為了鞏固前端知識,決定用Vue來做這個專案的移動端網站,我本人Vue是從零開始的,一邊學習一邊寫程式碼,在這裡記錄一下過程。 專案說明: 主要功能實現一個投資平臺,會員身份為融資人或投

從0開始學pyspark使用pyspark.ml.clustering模組對商場顧客聚類

資料下載: 資料為kaggle上的關於商場客戶的資料,地址:https://www.kaggle.com/vjchoudhary7/customer-segmentation-tutorial-in-python 資料準備: 資料集很小,四個特徵值:性別,年齡,收入能力,消費

ionic學習ionic3專案打包成手機瀏覽器、安卓apk專案

主要目的:將ionic專案打包成手機瀏覽器的專案,可以測試掃描二維碼等手機可用的功能。 步驟: 1. 新增瀏覽器打包環境 ionic cordova platform add browser   2. 打包:   ionic