将Makefile与子文件夹一起使用

时间:2016-10-06 01:08:03

标签: makefile gnu-make

我有以下目录结构。

Project/
    ├── bin/
    ├── src/
    │    ├── main.c
    │    ├── util/
    │         ├── util.c
    │         ├── util.h
    ├── obj/
    ├── .depend/

我的所有源代码都在src文件夹中。在src中,root是我的main.c文件;其中包括与他(或同一级别文件夹)处于同一级别的其他文件。我有一个Makefile,适用于同一级别的main.c中的所有文件,但不适用于src中子文件夹中的文件

如何更改我的Makefile以允许src文件夹中的子文件夹?

CC := gcc
CFLAGS := -Wall -Wextra
BINDIR := bin
OBJDIR := obj
SRCDIR := src
DEPDIR := .depend
SOURCES := $(wildcard $(SRCDIR)/*.c)
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SRCDIR)/%.c, $(DEPDIR)/%.d, $(SOURCES))

$(BINDIR)/app: $(OBJECTS) | $(BINDIR)
    @$(CC) -o $@ $^

-include $(DEPENDS)

$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
    @$(CC) $(CFLAGS) -c -o $@ $<

$(DEPDIR)/%.d: $(SRCDIR)/%.c | $(DEPDIR)
    @$(CC) -MM -MG $< | sed 's!^\(.\+\).o:!$(DEPDIR)/\1.d $(OBJDIR)/\1.o:!' > $@

$(DEPDIR) $(BINDIR) $(OBJDIR):
    @mkdir $@

clean:
    @rm -rf $(BINDIR)/*
    @rm -rf $(OBJDIR)/*

.PHONY: clean

编辑.o.d文件不需要尊重结构的原始设计。我正在使用Windows(MinGW)

2 个答案:

答案 0 :(得分:2)

首先,您必须更改SOURCES以递归查找来源。这可以在纯粹的make中完成:

subdirs = $(filter-out $1,$(sort $(dir $(wildcard $1*/))))
rfind = $(wildcard $1$2) $(foreach d,$(call subdirs,$1),$(call rfind,$d,$2))

SOURCES := $(call rfind,$(SRCDIR)/,*.c)

除目录创建外,其他所有内容都可以。首先,更改先前条件以使用$(@D)进行二次扩展:

.SECONDEXPANSION:

$(OBJDIR)/%.o: $(SRCDIR)/%.c | $$(@D)
    ...
$(DEPDIR)/%.d: $(SRCDIR)/%.c | $$(@D)
    ...

然后,更改目录创建规则以包含所有目录:

$(BINDIR) $(patsubst %/,%,$(sort $(dir $(OBJECTS) $(DEPENDS)))):
    @mkdir -p $@

与递归查找一样,它使用sort对目录进行重复数据删除(否则make会发出警告)并删除尾部斜杠(因为$(@D)不会有尾部斜杠)。请注意,需要-p来避免订单问题,并且目录只包含其他目录且没有源。

答案 1 :(得分:0)

尝试设置这样的来源:

SOURCES := $(shell find $(SRCDIR) -type f -name "*.c")

如果它无法正常工作,请尝试通过在命令行中运行来调试它

find src -type f -name "*.c"

并查看它是否输出正确的文件列表并使用正确的相对路径进行相应调整。

请注意,此方法仅适用于类似unix的环境,如果您在MSYS或Cygwin环境中使用MinGW,它应该可以正常工作。