• 从头開始写项目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 来全面禁止命令的显示。



  • 相关阅读:
    C++ 使用老牌库xzip & unzip对文件进行压缩解压
    第一次玩蛇,有点紧张。
    fiddler 抓取手机http/https包
    disk或者Partition镜像的制作
    VS2013+phread.h环境配置
    C++ 浅谈 strlen 与 sizeof的区别
    Qt 显示网页的控件
    Qt error: C2236: 意外的标记“class”。是否忘记了“;”?
    初识MySQL——人生若如初相逢
    【学习笔记】HTML基础:列表、表格与媒体元素
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6742930.html
Copyright © 2020-2023  润新知