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

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

时间: 2024-10-09 15:32:29

从头开始写项目Makefile(十):make内嵌函数及make命令显示的相关文章

Makefile---make内嵌函数及make命令显示 (九)

原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/ 这一节我们讲一下make的函数,在之前的章节已经讲到了几个函数:wildcard.patsubst.notdir.shell等.一般函数的调用格式如下: $(funcname arguments) 或 $(funcname arguments) 其中funcname是需要调用函数的函数名称,应该是make内嵌函数:arguments是函数参数,参数和函数名之间使用空格分割,如果存在多个参 数时

从头开始写项目Makefile(六):参数传递、条件判断、include

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 在多个Makefile嵌套调用时,有时我们需要传递一些参数给下一层Makefile.比如我们在顶层Makefile里面定义的打开调试信息变量DEBUG_SYMBOLS,我们希望在进入子目录执行子Makefile时该变量仍然有效,这是需要将该变量传递给子Makefile,那怎么传递呢?这里有两种方法: 1.     在上层Makefile中使用"export&qu

从头开始写项目Makefile(四):伪目标

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一般情况下,Makefile都会有一个clean目标,用于清除编译过程中产生的二进制文件.我们在第一节的Makefile就用到了这个 clean目标,该目标没有任何依赖文件,并且该目标对应的命令执行后不会生产clean文件. 像这种特点目标,它的规则所定义的命令不是去创建文件,而仅仅通过make指定目标来执行一些特定系统命令或其依赖为目标的规则(如all),称为

从头开始写项目Makefile(五):嵌套执行

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 在大一些的项目里面,所有源代码不会只放在同一个目录,一般各个功能模块的源代码都是分开的,各自放在各自目录下,并且头文件和.c源文件也会有各自的目录,这样便于项目代码的维护.这样我们可以在每个功能模块目录下都写一个Makefile,各自Makefile处理各自功能的编译链接工作,这样我们就不必把所有功能的编译链接都放在同一个Makefile里面,这可使得我们的Ma

从头开始写项目Makefile(三):变量的使用

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 仔细研究我们的之前Makefile发现,我们还有改进的地方,就是此处: target_bin : main.o debug.o ipc.o timer.o tools.o >---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o 如果增加一个源文件xx.c的话,需要在两处或多处增加xx.o文件.我们可以

从头开始写项目Makefile(零):前言

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一不小心工作三年了,也就是写了三年代码了,码农生活过的真快.最近发现我们项目的Makefile不够好,于是着手改了一下,以前Makefile写好后就很少动它了,直接在项目之间拷来拷去直接拿来用,这次重新修改项目Makefile,发现自己又学到不少东西,于是乎决定总结一下记录下来与各位苦逼的程序猿一道分享一下. 其实各大论坛博客已经有很多关于Makefile的文章

从头开始写项目Makefile(一):基本规则

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一般一个稍大的linux项目会有很多个源文件组成,最终的可执行程序也是由这许多个源文件编译链接而成的.编译是把一个.c或.cpp文件编译成中间代码.o文件,链接是就使用这些中间代码文件生成可执行文件.比如在当前项目目录下有如下源文件: # ls common.h debug.c debug.h ipc.c ipc.h main.c tags timer.c ti

从头开始写项目Makefile(二):自动推导

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 上一节的Makefile勉强可用,但还写的比较繁琐,不够简洁.对每一个.c源文件,都需要写一个生成其对应的.o目标文件的规则,如果有几百个或上千个源文件,都手动来写,还不是很麻烦,这也不够自动化啊. 这样,我们把生成.o目标文件的规则全部删除掉,就是这样一个Makefile文件: target_bin : main.o debug.o ipc.o timer.o

从头开始写项目Makefile(九):目录搜索

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 在一个较大的工程中,一般会将源代码和二进制文件(.o 文件和可执行文件)安排在不同的目录来进行区分管理.这种情况下,我们可以使用 make 提供的目录搜索依赖文件功能(在指定的若干个目录下自动搜索依赖文件).在Makefile中,使用依赖文件的目录搜索功能.当工程的目录结构发生变化后,就可以做到不更改 Makefile的规则,只更改依赖文件的搜索目录. 在我们上