将Makefile与子文件夹一起使用

将Makefile与子文件夹一起使用,makefile,gnu-make,Makefile,Gnu Make,我有以下目录结构 Project/ ├── bin/ ├── src/ │ ├── main.c │ ├── util/ │ ├── util.c │ ├── util.h ├── obj/ ├── .depend/ 我所有的源代码都在src文件夹中。src根目录中是我的主.c文件;其中包括与他处于同一级别(或在同一级别文件夹中)的其他文件。我在下面有一个Makefile,它适用于mai

我有以下目录结构

Project/
    ├── bin/
    ├── src/
    │    ├── main.c
    │    ├── util/
    │         ├── util.c
    │         ├── util.h
    ├── obj/
    ├── .depend/
我所有的源代码都在src文件夹中。src根目录中是我的主.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
CC:=gcc
CFLAGS:=-Wall-Wextra
BINDIR:=bin
OBJDIR:=obj
SRCDIR:=src
DEPDIR:=.dependen
来源:=$(通配符$(SRCDIR)/*.c)
对象:=$(patsubst$(SRCDIR)/%.c,$(OBJDIR)/%.o,$(源代码))
依赖项:=$(patsubst$(SRCDIR)/%.c,$(DEPDIR)/%.d,$(源))
$(BINDIR)/应用程序:$(对象)|$(BINDIR)
@$(CC)-o$@$^
-包括美元(视情况而定)
$(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$@
清洁:
@rm-rf$(宾迪尔)/*
@rm-rf$(OBJDIR)/*
.假冒:干净

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

尝试如下设置您的源代码:

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

如果它不能正常工作,试着通过在命令行中运行来调试它

find src-type f-name“*.c”

并查看它是否输出了正确的文件列表以及正确的相对路径,并进行相应调整


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

请尝试如下设置源代码:

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

如果它不能正常工作,试着通过在命令行中运行来调试它

find src-type f-name“*.c”

并查看它是否输出了正确的文件列表以及正确的相对路径,并进行相应调整


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

首先,您必须更改
源代码以递归方式查找源代码。这可以通过纯制造完成:

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
,以避免顺序问题和目录仅包含其他目录而不包含源的问题。

首先,您必须更改
源以递归查找源。这可以通过纯制造完成:

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
,以避免订单问题和目录仅包含其他目录而不包含源的问题。

您需要指定更多详细信息。例如,您希望在何处为子目录中的源文件创建
.o
.d
文件:它们是在同一平面目录中创建的,还是在等效的子目录中创建的。您还需要指定您的平台,因为可能会使用特定于平台的工具。抱歉,.o和.d文件不需要尊重结构的原始设计。我正在使用Windows(MinGW),您需要为对象文件生成同构的目录结构。使用纯make是可能的,但是最初的样板代码有点冗长。我正在考虑为此创建一个github回购。@MaximEgorushkin,看看这个:@igagis有趣。不过,每个目标一个makefile有点不方便。您需要指定更多详细信息。例如,您希望在何处为子目录中的源文件创建
.o
.d
文件:它们是在同一平面目录中创建的,还是在等效的子目录中创建的。您还需要指定您的平台,因为可能会使用特定于平台的工具。抱歉,.o和.d文件不需要尊重结构的原始设计。我正在使用Windows(MinGW),您需要为对象文件生成同构的目录结构。使用纯make是可能的,但是最初的样板代码有点冗长。我正在考虑为此创建一个github回购。@MaximEgorushkin,看看这个:@igagis有趣。不过,每个目标一个makefile有点不方便。