假设我有一个 C 项目。有几个文件:
/myproject/makefile
/myproject/src
/myproject/build
/myproject/src/baseHeader.h
/myproject/src/module1/module1.h
/myproject/src/module1/module1_a.c
/myproject/src/module1/module1_b.c
/myproject/src/main.c
我希望 make 在 src 中搜索所有不在第一深度级别的 *.h 文件,即 make 应该在
中查找 *.h 文件/myproject/src/module1/
所以它不会使用
/myproject/src/baseHeader.h
然后,对于每个找到的 .h,make 应该使用 .h 的基名创建目标,即
/myproject/src/module1/module1.h
应该是
./build/module1.o: ./src/module1/module1_a.c ./src/module1/module1_b.c ./src/module1/module1.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $< -o $@
它还应该为/myproject/src/dir 中的每个 .c 文件创建目标,而无需递归,在此示例中,只会找到 main.c 并且目标应该如下所示
./build/main.o: ./src/main.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)
如何做到这一点? 有人可以向我提供示例的链接(如果存在)吗?
我之所以要求这个,是因为经过一天的尝试,我认为最好忘记 make 并使用 bash 脚本......
最佳答案
这是可以做到的,但并不是微不足道的。一种方法是在 src
目录及其子目录中递归地构建所有 .h
文件的列表,然后从该列表中删除 。
文件。src
目录中的 h
我们可以使用 $(wildcard src/**/*.h))
在 src 目录和所有子目录中搜索 .h
文件,并且仅在 src 目录中搜索带有 $(通配符 src/*.h) 的 .h
文件。这些可以与 filter-out 结合使用函数生成一个仅包含 src/
子目录中的 .h
文件的列表,例如
MODULES := $(filter-out $(wildcard src/*.h),$(wildcard src/**/*.h))
这将产生一个类似的列表
/myproject/src/module1/module1.h
/myproject/src/module2/module2.h
/myproject/src/module3/module3.h
我们可以删除目录结构
INCLUDES := $(notdir MODULES)
这将产生
module1.h
module2.h
module3.h
我们可以将它们转换为模块的目标文件
OBJDIR = build
OBJS := $(addprefix $(OBJDIR)/, $(patsubst %.h,%.o, $(INCLUDES)))
然后我们定义一个空目标规则来创建所有这些
.PHONY: modules
modules: $(OBJS)
以及创建对象的隐式规则
$(OBJDIR)/%.o: $(dir $(findstring %.h, $MODULES))*.c %.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $? -o $@
编辑:在先决条件列表中使用通配符并不是特别建议,但这是我目前拥有的最佳解决方案。
为了在不递归搜索的情况下为 src
中的每个 .c
文件编译目标,我们首先采用类似的方法。
SRCS := $(wildcard src/*.c)
将找到顶级src
目录中的所有.c
文件。我们可以使用这些来编译目标
$(SRCS:%.c=$(OBJDIR)/%.o): %.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)
关于c - 具有自动目标创建功能的潜在大型项目的 Makefile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31728451/