Makefile学习(二)
一、makefile常用函数
1、字符串替换函数,函数使用格式如下
$(subst from,to,text)
OBJ=$(subst ee,EE,feet on the street)
all:
@echo $(OBJ)
执行 make 命令,我们得到的值是“fEEt on the strEEt”。
2、取后缀名函数,函数使用格式如下:
$(suffix names)
OBJ=$(suffix src/foo.c hacks)
all:
@echo $(OBJ)
执行 make 命令,我们得到的值是“.c ”。文件 “hacks” 没有后缀名,所以返回的是空值。
3、获取匹配模式文件名函数,命令使用格式如下:
$(wildcard PATTERN)
函数说明:函数的功能是列出当前目录下所有符合模式的 PATTERN 格式的文件名。返回值为空格分隔并且存在当前目录下的所有符合模式 PATTERN 的文件名。实例:
OBJ=$(wildcard *.c *.h)
all:
@echo $(OBJ)
执行 make 命令,可以得到当前函数下所有的 ".c " 和 “.h” 结尾的文件。
二、命令回显与执行
命令回显:
通常 make 在执行命令行之前会把要是执行的命令行输出到标准输出设备。我们称之为 “回显”,就好像我们在 shell 环境下输入命令执行时一样。如果规则的命令行以字符“@”开始,则 make 在执行的时候就不会显示这个将要被执行的命令。
OBJ=test main list
all:
@echo $(OBJ)
执行时将会得到test main list这条输出信息,如果在执行命令之前没有字符“@”,那么make的输出将是 echo test main list。
命令执行:
在 Makefile 中书写在同一行中的多个命令属于一个完整的 shell 命令行,书写在独立行的一条命令是一个独立的 shell 命令行。
三、makefile的嵌套执行
subsystem :
$(MAKE) -C subdir
这个例子可以这样来理解,在当前目录下有一个目录文件 subdir 和一个 Makefile 文件,子目录 subdir 文件下还有一个 Makefile 文件,这个文件是用来描述这个子目录文件的编译规则。
例子:
假设有一个 MP3 player 的应用程序,它可以被划分为若干个组件:用户界面(ui)、编解码器(codec)以及数据管理库(db)。它们分别可以用三个程序库来表示:libui.a、libcodec.a 和 libdb.a。将这些组件紧凑的放到一起就可以组成这个应用程序。具体的文件结构展示为(我们展示的只是目录文件,没有展示详细的源文件):
├──Makefile //最外层的Makefile文件,不是目录文件。
├──include //编译的时候需要链接的库文件
│ ├──codec //libui.a 库文件所在的目录
│ ├──db //libdb.a 库文件所在的目录
│ ├──ui //libui.a库文件所在的目录
├──lib //源文件所在的目录,子目录文件中包含Makefile文件
│ ├──codec //编解码器所在的源文件的目录
│ ├──db //数据库源文件所在的目录
│ ├──ui //用户界面源文件所在目录
├──app
│ ├──player
└──doc //这个工程编译说明
我们可以看到最外层有一个 Makefile 文件,这就是我们的 “总控Makefile” 文件,我们使用这个 Makefile 调用项目中各个子目录的 Makefile 文件的运行。假设只有我们的 lib 目录下和 app 目录下的各个子目录含有 Makefile 文件。那我们总控的 Makefile 的文件可以这样来写:
lib_codec := lib/codec
lib_db := lib/db
lib_ui := lib/ui
libraries := $(lib_codec) $(lib_db) $(lib_ui)
player := app/player
.PHONY : all $(player) $(libraries)
all : $(player)
$(player) $(libraries) :
$(MAKE) -C $@