makefile - 使用 Make 的多个嵌套目录
问题描述
我有这个 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 技巧来帮助支持嵌套目录?
解决方案
查找子目录和子子目录中的所有源文件:
SRCS := $(wildcard $(SRCDIR)/*.c $(SRCDIR)/*/*.c)
为什么要做“objects”/“prefix_objects”这件事?只需制作目标文件:
OBJS := $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS))
编写一个规则,obj
从src
. 创建目标目录:
$(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))
推荐阅读
- python - 在class1中调用class2时出现AttributeError,class1没有__init__属性
- java - 关于 CodeName One 和 Path Java Runtime 的问题
- reactjs - 使用本地存储中的承载令牌
- c++ - 如何在 C++ 中为 std::list 参数设置默认值?
- c++ - 按空格分割字符串并将列输出到不同的数组中
- angular - 如何构建项目以便只有 index.html 位于根目录?
- python - numpy 随机选择和 networkx 图表列表
- django-rest-framework - 如何删除 ViewSet 中的任何文件
- php - 使用 PHP 变量在 MySQLi 中的 Carousel 中显示图像
- android - WebView 没有在 Android 中加载本地 HTML?