关于Makefile静态模式

静态模式形如:

$(OBJS): $(objdir)/%.o: %(srcdir)/%.c

$(CC) -c $(CFLAGS) $< -o $@

可以非常方便帮我们编译某文件夹下的所有.c (或.c++/.cc/.cpp等)文件,配合命令wildcard 、patsubst 、notdir 命令,可以非常方便指定源目录及中间文件目录等。

首先介绍上文中提到的三个命令(可以自行百度、Google),以下权当作个人记录

SRCS = $(wildcard $(DIR)/*.c) //提取DIR目录下所有.c文件,附带目录

CSRCS = $(notdir $(SRCS)) //提取所有文件,只包含文件名及后缀

OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(CSRCS)) //将所有CSRCS中的.c文件后缀改为.o,并增加目录OBJDIR

举个例子:

1. 新建src文件夹,并于该文件夹下建立sr1.c sr2.c sr3.c 三个文件

2. 于src平级文件夹下建立obj文件夹

建立Makefile文件,写入以下语句:


DIR := ./src
OBJDIR := ./obj

SRCS = $(wildcard $(DIR)/*.c)
CSRCS = $(notdir $(SRCS))
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(CSRCS))

all:
@echo $(SRCS)
@echo $(CSRCS)
@echo $(OBJS)

目录结构如下:

|-.
  |-obj
  |-src
    |-sr1.c
    |-sr2.c
    |-sr3.c
  |-Makefile


在当前文件夹下执行make,可以得到:

SRCS 内容为:./src/sr1.c ./src/sr2.c ./src/sr3.c //取出所有.c文件并带着目录信息

CSRCS 内容为:sr1.c sr2.c sr3.c//去除目录信息,为了给将.o文件放入其他目录

OBJS 内容为:./obj/sr1.o ./obj/sr2.o ./obj/sr3.o//为.o文件加上目录信息

至此,在OBJS中保存了需要编译的所有中间文件,但此时文件并未生成,需要gcc编译得到

$(OBJS):$(OBJDIR)/%.o:$(DIR)/%.c

$(CC) -c $(CFLAGS) $< -o $@

使用make执行以上脚本,则可在./obj文件夹下得到sr1.o sr2.o sr3.o三个中间文件

这里简单解释:

1. 在Makefile静态模式中,中间项(两个:之间的项,这里是$(OBJDIR)/%.o)用于匹配首项(这里是$(OBJS))中的内容,由于OBJS中所有文件均类似$(OBJDIR)/filename.o,以$(OBJDIR)/%.o进行匹配,则%代表了filename也即是去除了后缀的文件名,再将此文件名跟上.c后缀并加上$(DIR)文件信息,则可以确定源文件位置

2. OBJS中所有项为$(OBJDIR)/filename.o 是为了保证gcc生成的中间文件全部位于$(OBJDIR)目录下,便于整理以及清理工作。

3. 注意:

a) 就上例而言,若中间项形如$(OBJDIR)/%.o,则%分别代表了sr1 、sr2、sr3

b)若中间项形如%.o,则 % 分别代表了$(OBJDIR)/sr1 、$(OBJDIR)/sr2、$(OBJDIR)/sr3, 这样匹配,将导致第三项$(DIR)/%.c变为 $(DIR)/$(OBJDIR)/sr1.c 、$(DIR)/$(OBJDIR)/sr2.c 、$(DIR)/$(OBJDIR)/sr3.c 最终导致无法找到源文件

c)在命令中,表示源文件的是"$<" 而不是 "$^",后者代表所有源的集合


进行以上操作之后,可将src目录下的所有.c文件生成的中间文件存入obj目录,如果有大量.c文件需要编译,使用该方法能够有效减轻Makefile文件大小,并使其干净、整洁

你可能感兴趣的:(IT)