Makefile学习7 - 静态模式规则与动态库编译
一. 前言
本文以一个动态库编译的Makefile作为实例,讲解make中的静态模式规则的使用,加深对Makefile全方面的学习,达到学以致用的目的。
二. 静态模式规则
1. 语法
TARGETS ...: TARGET-PATTERN: PREREQ-PATTERNS ...
COMMANDS
...
从上面的语法规则可以看出,静态模式规则包含三部分:TARGETS,TARGET-PATTERN和PREREQ-PATTERNS。
TARGETS:列出此规则的一系列目标文件,可以包含通配符。
TARGET-PATTERN:目标模式。一般会包含"%",其中"%"可以匹配目标文件中的任何部分,匹配的部分称为"茎",此外,目标文件和目标模式的其余部分必须精确的匹配,例如:
目标文件:foo.o
目标模式:%.o
茎:foo -> 模式符合
目标文件:foo.c
目标模式:%.o
茎:无 -> 模式不符合
PREREQ-PATTERNS:依赖模式。每个目标的依赖文件使用目标模式的"茎"代替依赖模式中的"%"而得到。举例如下:
目标文件:foo.o
目标模式:%.o
目标依赖:%.c
根据目标文件foo.o和目标依赖%.o,由上面介绍可以得出,"茎"是"foo",所以目标依赖%.c中%可以替换为foo,所以目标依赖就是foo.c了。
2. 举例
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
根据上面语法的解释可知:该Makefile的目标文件是foo.o bar.o,目标模式是%.o,目标依赖是%.c。根据目标文件和目标模式,得出"茎"是foo和bar,所以目标模式时foo.o和bar.o,目标依赖是foo.c和bar.c。所以,相当于如下规则:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
二. 动态库编译举例
1. 代码结构
├── include
│ ├── a.h
│ ├── b.h
│ ├── c.h
│ └── d.h
├── obj
└── src
├── a.c
├── b.c
├── c.c
└── d.c
2. 目的
将src中的所有C语言文件,编译成一个libtest.so的动态库,编译出的目标文件文件和库都放在obj目录下。
3. Makefile编写
INCDIR := include
SRCDIR := src
OBJDIR := obj
TARGET := libtest.so
SRCS := $(wildcard $(SRCDIR)/*)
OBJS := $(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
CFLAGS += -Wall -g -I include -fPIC
LDFLAGS += -fPIC -shared
$(OBJDIR)/$(TARGET):$(OBJS)
gcc $(LDFLAGS) $^ -o $@
$(OBJS):$(OBJDIR)/%.o:$(SRCDIR)/%.c
@mkdir -p $(OBJDIR)
gcc $(CFLAGS) -c $< -o $@
.PHONY:clean
clean:
@rm -rf $(OBJDIR)/*
上面的例子($(OBJS):$(OBJDIR)/%.o:$(SRCDIR)/%.c)就使用了Makefile的静态模式规则,其中OBJS是目标文件(obj/a.o obj/c.o obj/b.o obj/d.o),而$(OBJDIR)/%.o是目标模式(obj/%.o),所以,"茎"分别为a,b,c和d,目标依赖则为src/a.c,src/b.c,src/c.c和src/d.c。这块代码的作用是分别将各个C语言文件编译成目标文件。
最后,$(OBJDIR)/$(TARGET):$(OBJS)规则,将所有目标文件编译为最终的动态库。
三. 总结
本文讲解了Makefile的静态模式规则的使用,并通过一个动态库编译的例子,加深了对静态模式规则的理解。