具有自动目标创建功能的潜在大型项目的 Makefile

Makefile for potentially large project with automatic target creation

假设我有一个 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/ 目录中的每个 .c 文件创建目标,而不是在这个例子中递归,只有 main.c 会被找到并且目标应该看起来像

./build/main.o: ./src/main.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)

如何做到这一点? 如果存在,有人可以向我提供 link 示例吗?

我问这个是因为经过一天的尝试,我认为最好忘记制作并改用 bash 脚本...

这可以做到,但并非微不足道。一种方法是在 src 目录及其子目录中递归地构建所有 .h 文件的列表,然后从该列表中删除 [=20] 中的 .h 文件=] 目录.

我们可以使用 $(wildcard src/**/*.h)) 在 src 目录和所有子目录中搜索 .h 个文件,使用 $(wildcard src/*.h) 仅搜索 .h 个文件的 src 目录。这些可以与 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)