程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 從頭開始寫項目Makefile(十):make內嵌函數及make命令顯示

從頭開始寫項目Makefile(十):make內嵌函數及make命令顯示

編輯:C++入門知識

從頭開始寫項目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) :
>---@echo "   MKDIR $(notdir $@)..."
>---@mkdir -p $@

ifneq ($(SRC_BIN),)
$(BINDIR)/$(SRC_BIN) : $(SRC_OBJ)
>---@echo "   LINK $(notdir $@)..."
>---@$(CC) -o $@ $^ $(LDFLAGS)
endif

ifneq ($(SRC_LIB),)
$(LIBDIR)/$(SRC_LIB) : $(SRC_OBJ)
>---@echo "    ARCHIVE $(notdir $@)..."
>---@$(AR) rcs $@ $^
>---@echo "    COPY $@ to $(SRC_BASE)/libs"
>---@cp $@ $(SRC_BASE)/libs
endif

$(SRC_OBJ) : $(OBJDIR)/%.o : %.c
>---@echo "    COMPILE $(notdir $<)..."
>---@$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@


編譯輸出如下:
# 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):
>---@echo "    Create directory $@ ..."
>---mkdir -p $(BUILDDIR)/bin $(BUILDDIR)/lib

$(MODULES):
>---@$(MAKE) -C $(DIR)/$@ MODULE=$@ --no-print-directory

main:tools ipc

clean :
>---@for subdir in $(MODULES); \
>---do $(MAKE) -C $(DIR)/$$subdir MODULE=$$subdir $@ --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 來全面禁止命令的顯示。



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved