【问题标题】:Multiple Nested Directories with Make使用 Make 的多个嵌套目录
【发布时间】:2020-08-10 21:53:53
【问题描述】:

我有这个 Makefile。

# Variables
CC = gcc
CFLAGS = -Wall -g -c
ODUMP = objdump
ODFLAGS = -d

# Directories
OBJDIR := obj
TGTDIR := target
SRCDIR := src
DMPDIR := dump

# Sources list
SRCS := main.c kernel.c
# Sources location
VPATH := src:../headers

# Objects list
objects = $(notdir $(patsubst %.c,%.o,$(addprefix $(SRCDIR)/,$(SRCS))))
# Objects list with prefix
prefix_objs = $(addprefix $(OBJDIR)/, $(objects))

# Target name
target = main

$(target) : $(prefix_objs)
    $(CC) -o $(TGTDIR)/$@ $(prefix_objs)

$(OBJDIR)/%.o: %.c | folders
    $(CC) $(CFLAGS) -o $@ $<
    $(ODUMP) $(ODFLAGS) $@ > $(DMPDIR)/$@

folders:
    mkdir -p $(OBJDIR)
    mkdir -p $(TGTDIR)
    mkdir -p $(DMPDIR)/$(OBJDIR)

.PHONY: clean
clean:
    rm -rf $(OBJDIR) $(TGTDIR) $(DMPDIR) *.o

我希望能够支持嵌套在 src 目录下的至少一层深度的“模块或功能”。我也希望能够不必手动构建 # Sources list SCRS := main.c kernel.c 我的文件夹结构如下

| dump
| obj
| src ----
    | kernel.c
    | kernel.h
    | main.c
| target
| .gitignore
| Makefile
| README.md

不过,我希望能够支持。

| dump
| obj
| src ----
    | kernel ----
        | kernel.h
        | thing.c
        | kernel.c
        | any.c
    | feature1 ----
        | ...whatever files
    | main.c
| target
| .gitignore
| Makefile
| README.md

如果你看看我的folders 规则。我必须显式创建$(DMPDIR)/$(OBJDIR),因为$(OBJDIR)/%.o 目标会添加前缀,即使对于转储文件也是如此。如果我开始为我的“功能”添加文件夹,我也需要支持 mkdir,因为它是obj/kernel/kernal.o。我还需要列出 SRCS 中的每个文件......现在使用 VPATH 的推荐方式也已经崩溃,因为它不再只是 src。似乎增加了一个新的要求已经增加了扩展这个 Makefile 的难度。是否有任何 GNU Make 技巧来帮助支持嵌套目录?

【问题讨论】:

  • 是否要在obj/中重新创建src/的目录结构?
  • @Beta 我对此并不特别关心。如果我猜我有重复的文件名,结构可能会很好。

标签: makefile gnu-make


【解决方案1】:

在子目录和子子目录中查找所有源文件:

SRCS := $(wildcard $(SRCDIR)/*.c $(SRCDIR)/*/*.c)

为什么要做“objects”/“prefix_objects”这件事?只需制作目标文件:

OBJS := $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS))

编写一条规则,从src 中的源文件创建obj 中的目标文件。创建目标目录:

$(OBJDIR)/%.o : $(SRCDIR)/%.c
        @mkdir -p $(@D) $(DMPDIR)/$(@D)
        $(CC) $(CFLAGS) -o $@ $<
        $(ODUMP) $(ODFLAGS) $@ > $(DMPDIR)/$@

修正你的链接线:

$(TGTDIR)/$(target) : $(OBJS)
        $(CC) -o $@ $^

如果你真的不想做规则中的mkdir,你可以这样:找到所有包含对象的目录,然后创建它们:

OBJDIRS := $(sort $(dir $(OBJS)))

folders :
        mkdir -p $(TGTDIR) $(OBJDIRS) $(addprefix $(DMPDIR)/,$(OBJDIRS))

【讨论】:

  • 我为这些更改的输出添加了一个编辑。
  • nvm 我看到我忘记了OBJS := ... 步骤
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多