具有自动目标创建功能的潜在大型项目的 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)
假设我有一个 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)