从头开始写项目Makefile(十):make内嵌函数及make命令显示【转】

简介: 转自:http://blog.csdn.net/shallnet/article/details/38314473#comments 版权声明:本文为博主原创文章,未经博主允许不得转载。如果您觉得文章对您有用,请点击文章下面“顶”。

转自:http://blog.csdn.net/shallnet/article/details/38314473#comments

版权声明:本文为博主原创文章,未经博主允许不得转载。如果您觉得文章对您有用,请点击文章下面“顶”。
   【版权声明:转载请保留出处: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”的文件名。
例如:
[html] view plain copy

    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”中的那个“%”所代表的字符串。
例如:
[html] view plain copy

    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源文件。如下两种使用可以得到同一种结果::
[html] view plain copy

    $(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在编译时会打印出当前正在执行的命令,当编译链接选项很长时,会输出很多东西在屏幕上,如果我 不想再屏幕上看到很多东西,我们可以在命令前面加上@,这样命令就不会输出到屏幕了。我们这样尝试修改下:
[html] view plain copy

    # 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......"
这样可以输出目前正在做的事,又不会输出正在执行命令。现在将规则修改下如下:
[html] view plain copy

    $(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 $@  



编译输出如下:
[html] view plain copy

    # 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规则修改如下:
[html] view plain copy

    $(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 来全面禁止命令的显示。

 

【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
【中级软件设计师】—(下午题)试题三精讲总结(四十二)
【中级软件设计师】—(下午题)试题三精讲总结(四十二)
|
计算机视觉 Python
【Python】已解决:ModuleNotFoundError: No module named ‘cv2’
【Python】已解决:ModuleNotFoundError: No module named ‘cv2’
7020 0
rviz 启动出现没有链接 - Inconsistency detected by ld.so:
rviz 启动出现没有链接 - Inconsistency detected by ld.so:
990 1
rviz 启动出现没有链接 - Inconsistency detected by ld.so:
|
5天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
6801 46
|
2天前
|
人工智能 安全 API
CoPaw:3分钟部署你的 AI助理
源自阿里巴巴开源生态的个人 AI 助理——CoPaw。作为阿里倾力打造的开源力作,CoPaw 完美打通钉钉、飞书、Discord 等多平台对话通道,支持定时任务自动化。内置 PDF/Office 深度处理、新闻摘要等强大技能,更开放自定义扩展接口。坚持数据全程私有化部署,绝不上传云端,让每一位用户都能在大厂技术加持下,拥有安全、专属的智能助手。
|
6天前
|
人工智能 JSON JavaScript
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
手把手教你用 OpenClaw(v2026.2.22-2)+ 飞书,10分钟零代码搭建专属AI机器人!内置飞书插件,无需额外安装;支持Claude等主流模型,命令行一键配置。告别复杂开发,像聊同事一样自然对话。
3195 9
手把手教你用 OpenClaw + 飞书,打造专属 AI 机器人
|
4天前
|
人工智能 自然语言处理 机器人
保姆级教程:Mac本地搭建OpenClaw及阿里云上1分钟部署OpenClaw+飞书集成实战指南
OpenClaw(曾用名Clawdbot、Moltbot)作为2026年最热门的开源个人AI助手平台,以“自然语言驱动自动化”为核心,支持对接飞书、Telegram等主流通讯工具,可替代人工完成文件操作、日历管理、邮件处理等重复性工作。其模块化架构适配多系统环境,既可以在Mac上本地化部署打造私人助手,也能通过阿里云实现7×24小时稳定运行,完美兼顾隐私性与便捷性。
2610 4
|
12天前
|
存储 人工智能 负载均衡
阿里云OpenClaw多Agent实战宝典:从极速部署到AI团队搭建,一个人=一支高效军团
在AI自动化时代,单一Agent的“全能模式”早已无法满足复杂任务需求——记忆臃肿导致响应迟缓、上下文污染引发逻辑冲突、无关信息加载造成Token浪费,这些痛点让OpenClaw的潜力大打折扣。而多Agent架构的出现,彻底改变了这一现状:通过“单Gateway+多分身”模式,让一个Bot在不同场景下切换独立“大脑”,如同组建一支分工明确的AI团队,实现创意、写作、编码、数据分析等任务的高效协同。
5271 31
|
4天前
|
人工智能 数据可视化 安全
Claude Code小白邪修指南:一键安装+语音增效,附阿里云极速部署OpenClaw/Clawdbot攻略
对于AI工具新手而言,Claude Code的原生安装流程繁琐、终端操作门槛高,让不少人望而却步。但2026年的今天,“邪修”玩法彻底打破这一壁垒——通过开源工具实现一键部署,用语音交互提升3-4倍效率,再搭配阿里云OpenClaw的稳定运行环境,让小白也能快速上手AI编程助手。本文将详解“邪修”核心技巧、语音增效方案,以及阿里云OpenClaw部署步骤,附带完整配置代码与避坑指南,帮助你轻松开启AI辅助工作新模式。
1725 0

热门文章

最新文章