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

原文地址:https://www.cnblogs.com/mofei004/p/9639491.html