生成包含头文件的文件头文件
Makefile with headers including headers
In app.c
:
#include "app.h"
In app.h
:
#include "model/world.h"
#include "controller/controller.h"
如何在makefile中编写app.o
的目标?我应该在先决条件中包括这三个头文件吗?
是的,你应该列出所有可能需要重新编译的app.c的依赖项。
你可能会发现g++ -MM app.c很有用:-MM会以make格式列出app.c的所有依赖项。你甚至可以自动化它,让你的makefile半自动地处理依赖关系。
app.o : app.c app.h model/world.h controller/controller.h
gcc -c app.c
是的,你需要包含所有三个头文件作为依赖项。Makefiles:如果:
右边的任何东西发生了变化,那么它需要重新制作左边的东西。如果你修复了控制器中的一个bug,并从其中一个函数中删除了三个参数,而应用又从控制器中调用了这个函数,那么应用就需要重新制作来处理这个变化。
否则,当应用程序走到控制器并请求带有5个参数的函数X时,新的和改进的控制器将不知道应用程序到底在说什么。将抛出错误。到处都是火和血。一切都以眼泪结束。
这是我如何解决这个问题的一个例子。gcc -MM
从给定源文件的include指令生成规则。在包含include指令的源文件上尝试一下,看看它的输出。
# src/x.c src/y.c ... => build/x.o build/y.o ...
OBJ = $(patsubst src/%.c,build/%.o,$(wildcard src/*.c))
# src/x.c src/y.c ... => build/x.d build/y.d ...
# `-> these files will include the generated rules
INCLUDE_PREQS = $(patsubst src/%.c,build/%.d,$(wildcard src/*.c))
all: main
main: $(OBJ)
gcc -o $@ $^
## compile object from src/x.c to build/x.o
# src/x.c src/y.c ... => build/x.o build/y.o
build/%.o : src/%.c
gcc -o $@ -c $<
## generate header prerequisite rules
# -MT $(patsubst build/%.d,build/%.o,$@)
# `-> set the generated target to be build/%.o
build/%.d: src/%.c
gcc -MM -MT $(patsubst build/%.d,build/%.o,$@) $< > $@
## include the generated rules
include $(INCLUDE_PREQS)
你永远不需要在makefiles中手动指定头文件依赖项。
将-MMD -MP
添加到编译器标志中。它将使编译器除了输出.o
文件外,还输出.d
文件。这些是指定依赖项的小make文件。然后将它们-include
放到主makefile中。
如下所示:
SOURCES := 1.c 2.c
program: $(patsubst %,%.o,$(SOURCES))
gcc $^ -o $@
%.c.o: %.c
gcc -MMD -MP $< -c -o $@
-include $(patsubst %,%.d,$(SOURCES))
这可能有帮助:
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
DEP = $(patsubst %.o, %.mm, $(OBJ))
include $(DEP)
app: $(OBJ)
$(CC) -o $@ $(OBJ)
.FORCE:
%.mm: .FORCE
$(CC) -MM $*.c > $*.mm
这里:DEP
是需要包含的依赖文件列表(以mm结尾)。有一条规则用于构建生成文件依赖的mm文件。您强制构建随后作为依赖项包含的依赖项,以检查您的实际依赖项
不,您不应该将头文件列为依赖项!这对于已经以#include
指令的形式存在的规范来说是多余的。迟早,冗余会引起问题,因为随着项目的发展,你最终会得到不一致的列表。
还有一个普遍但幼稚的误解,认为只有头文件是依赖项。这可能导致错误的构建,因为许多其他原因,如更改命令行开关,更改编译器或更改硬件架构,都被监视到。
这两个问题的解决方案是使用一个可靠的构建工具:makepp处理这些情况,甚至可以扫描包含文件中的子包含,当你启动它时,甚至还没有构建。
还有很多事情要做。除了做GNU make所能做的几乎所有事情之外,还有很多更有用的事情,您甚至可以使用一些Perl编程扩展您的make文件。
- 使用mongocxx驱动程序时包含头文件问题
- 如何为包含头文件的目标编写生成文件?
- 如何在 CMakeLists.txt Qt Creator 中包含头文件?
- 当包含头文件的文件不在根项目文件夹中时,如何包含它
- 在生成文件先决条件中包含头文件的原因
- My Project的属性配置正确,但Visual Studio仍然无法打开包含头文件
- 在 PostgreSQL C 扩展中包含头文件
- 是否可以在C++中以间接方式包含头文件
- 是否需要包含头文件?
- 如何在不包含完整的文件系统头的情况下使用文件系统的类路径C++17?
- 我收到未声明的标识符错误,但我已包含头文件?
- 为什么我们需要构建一个提升库,仅仅包含头文件还不够吗,因为提升是模板
- C++:当顺序真正重要时,如何保证在项目中包含头文件的顺序
- 如何在C++中包含头文件时错误地重载
- 我在C++中无效使用不完整的类型类错误,如何正确包含头文件?
- 虚幻引擎4.16,C++包含头文件
- C++多次包含头文件
- 令牌之前的预期类名 '{' - 包含头文件和 CPP 文件
- 可以将标头文件包含在多个源文件中,而无需重复保护
- 有条件地将文件包含在C++标头中