makefile中的特殊符号及关键字
1.常见自动变量和含义
- * :表示目标文件的名称,不包含目标文件的扩展名。
- + :表示所有的依赖文件,这些依赖文件之间以空格分开,按照出现的先后为顺序,其中可能包含重复的依赖文件。
- < :表示依赖项中第一个依赖文件的名称
- ? : 依赖项中,所有目标文件时间戳晚的文件(表示修改过),依赖文件间以空格分开
- @ :目标项中目标文件的名称
- ^ :依赖项中,所有不重复的依赖文件,以空格分开。
2.预定义变量
Makefile中常用的变量及含义
AR | 生成静态库库文件的程序名称 | ar |
AS | 汇编编译器的名称 | as |
CC | C语言编译器的名称 | cc |
CPP | C语言预编译器的名称 | $(CC) -E |
CXX | C++语言编译器的名称 | g++ |
FC | FORTRAN语言编译器的名称 | f77 |
RM | 删除文件程序的名称 | rm -f |
ARFLAGS | 生成静态库库文件程序的选项 | 无默认值 |
ASFLAGS | 汇编语言编译器的编译选项 | 无默认值 |
CFLAGS | C语言编译器的编译选项 | 无默认值 |
CPPFLAGS | C语言预编译器的编译选项 | 无默认值 |
CXXFLAGS | C++语言编译器的编译选项 | 无默认值 |
FFLAGS | FORTRAN语言编译器的编译选项 | 无默认值 |
3.设置搜索路径
指定需要搜索的目录, make 会自动找到指定文件的目录并添加到文件上。
VPATH = path1:path2:...
4.递归make
对于规模比较大的程序,需要多个人在多个目录下进行开发。如果只用一个 Makefile 来维护就会比较麻烦,因此可以在每个目录下建立自己的 Makefile ,然后在总控 Makefile 中调用子目录的 Makefile 文件。
目录结构如下:
.
├── add
│ ├── add_float.c
│ ├── add.h
│ ├── add_int.c
│ └── Makefile
├── main.c
├── Makefile
└── sub
├── Makefile
├── sub_float.c
├── sub.h
└── sub_int.c
1.递归调用的方式
add:
cd add && $(MAKE)
它等价于
add:
$(MAKE) -C add
2.总控Makefile
CC = gcc CFLAGS = -O2 TARGET = cacu export OBJSDIR = $(shell pwd)/objs $(TARGET):$(OBJSDIR) main.o $(MAKE) -C add $(MAKE) -C sub $(CC) -o $(TARGET) $(OBJSDIR)/*.o $(OBJSDIR): mkdir -p $@ main.o:%.o:%.c $(CC) -c $< -o $(OBJSDIR)/$@ $(CFLAGS) -Iadd -Isub clean: -$(RM) $(TARGET) -$(RM) $(OBJSDIR)/*.o
如果总控 Makefile 中的一些变量需要传递给下层的 Makefile,可以使用 export 命令。如:
export OBJSDIR = ./objs
3.子目录Makefile的编写
Add 目录下的 Makefile 如下:
OBJS = add_int.o add_float.o all:$(OBJS) $(OBJS):%.o:%.c $(CC) -c $< -o $(OBJSDIR)/$@ $(CFLAGS) clean: $(RM) $(OBJS)
Sub 目录下的 Makefile 如下:
OBJS = sub_int.o sub_float.o all:$(OBJS) $(OBJS):%.o:%.c $(CC) -c $< -o $(OBJSDIR)/$@ $(CFLAGS) clean: $(RM) $(OBJS)
Makefile 中的函数
1.获取匹配模式的文件名wildcard
这个函数的功能是查找当前目录下所有符合模式 PATTERN 的文件名,其返回值是以空格分割的、当前目录下的所有符合模式 PATTERN 的文件名列表。其原型如下:
$(wildcard PATTERN)
例如,如下模式返回当前目录下所有扩展名位 .c 的文件列表。
$(wildcard *.c)
2.模式替换函数patsubst
这个函数的功能是查找字符串 text 中按照空格分开的单词,将符合模式 pattern 的字符串替换成 replacement。 Pattern 中的模式可以使用通配符, % 代表 0 个到 n 个字符,当 pattern 和 replacement 中都有 % 时,符合条件的字符将被 replacement 中的替换。函数的返回值是替换后的新字符串。其原型如下:
$(patsubst pattern, replacement, text)
例如,需要将 C 文件替换为 .o 的目标文件可以使用如下模式:
$(patsubst %.c, %.o, add.c)
上面的模式将 add.c 字符串作为输入,当扩展名为 .c 时符合模式 %.c ,其中 % 在这里代表 add,替换为 add.o,并作为输出字符串。
$(patsubst %.c, %.o, $(wildcard *.c))
输出的字符串将当前扩展名为 .c 的文件替换成 .o 的文件列表。
3.循环函数foreach
这个函数的原型为:
$(foreach VAR, LIST, TEXT)
函数的功能为 foreach 将 LIST 字符串中一个空格分割的单词,先传给临时变量 VAR ,然后执行 TEXT 表达式, TEXT 表达式处理结束后输出。其返回值是空格分割表达式 TEXT 的计算结果。
例如,对于存在 add 和 sub 的两个目录,设置 DIRS 为 "add sub ./" 包含目录 add、sub 和当前目录。表达式 $(wildcard $(dir)/*.c) ,可以取出目录 add 和 sub 及当前目录中的所有扩展名为 .c 的C语言源文件:
DIRS = sub add ./
FILES = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))
利用上面几个函数对原有的 Makefile 文件进行重新编写,使新的 Makefile 可以自动更新各个目录下的C语言源文件:
CC = gcc CFLAGS = -O2 -Iadd -Isub TARGET = cacu DIRS = sub add . FILES = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c)) OBJS = $(patsubst %.c, %.o, $(FILES)) $(TARGET):$(OBJS) $(CC) -o $(TARGET) $(OBJS) clean: -$(RM) $(TARGET) -$(RM) $(OBJS)
以上内容来源于:
http://www.cnblogs.com/OpenShiFt/
感谢分享!
1 #该文件用于当前目录下的c文件均为一个单独的程序 2 #后续可修改把目标文件通过参数指定 3 cc = gcc 4 #all:$(subst .c,.o,$(wildcard *.c)) 5 PROGS = client server 6 all: $(PROGS) 7 8 #%o:%.c 9 # gcc -o $@ $< 10 %: %.c 11 $(cc) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(LDLIBS) 12 13 clean: 14 rm -f $(PROGS) $(TEMPFILES) *.o
以上的内容基本可以阅读大部分makefile了。
更多关于makefiel函数的内容,下面的博文写的更全面。
makefile中常用函数 - CSDN博客 https://blog.csdn.net/yangxuan0261/article/details/52060582