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

标签 c makefile gnu

假设我有一个 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/

相关文章:

java - 打开文件时如何在 emacs 中自动缩进?

c - 在 C 中定义整数范围

c - 谁能告诉我它是怎么得到寄存器DS的值的

makefile - := and += in kernel Makefiles?有什么区别

c++ - CMake Exported Lib - 在客户端应用程序中找不到包含/lib 路径

c++ - 链接共享库依赖项未在 ldd 中列出

unix - 为什么一些 GNU 并行输入包含引号?

c - 字节交换结构

在子进程中创建线程

c++ - 我是否正确使用了 C++ 的 Makefile?