c++ - 为 C++ 项目创建 makefile
问题描述
我目前正在尝试编写一个 Makefile,它在当前目录和所有子目录中搜索 C++ 文件,然后将它们一一编译(如果它们自上次编译以来尚未编译或编辑)成在最终使用目标文件并将它们全部链接到最终程序之前,位于 ./Objects 位置的单个目标文件。
我已经弄清楚如何使用“shell find”命令查找所有文件。但是,我一直在试图弄清楚如何一次将源文件编译成对象文件。
这是我的代码:
Appname := App
#The Directory
ObjectsDir := ./Objects
#Find all the source files
SrcFiles = $(shell find . -name "*.cpp")
#Get their names only
SrcFilesName = $(notdir $(SrcFiles))
#Add a .o suffix for the Object files name
ObjectsSuffix = $(addsuffix .o, $(SrcFilesName))
#Add the prefix "Objects/" as I wish to output all the objects to ./Objects
#A Source Files such as "./Test/Source/Test.cpp" becomes "./Objects/Test.cpp.o"
Objects = $(addprefix ./Objects/, $(ObjectsSuffix))
#Compiler related Variables
CXX = g++
CXXFLAGS = -Wall -std=c++20 -fsanitize=address
CPPFLAGS = -DDEBUG -I ./Game/Headers -I ./Engine/Headers -I ./Engine/Headers/External
LDLIBS = $(shell sdl2-config --libs) -l dl
all : $(Appname)
$(Appname) : $(Objects)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(Objects) -o $(Appname) $(LDLIBS)
#The Problematic rule
#I would like this to run once per source file if they haven't been compiled or changed/edited, so that I don't end up recompiling the entire code base
$(ObjectsDir)/%.o: %.cpp
mkdir -p Objects
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MP -c $^ -o $@ $(LDLIBS)
注意:当所有源文件都在基本目录中时,makefile 当前可以工作。但是,当有更复杂的布局时,会出现多个子目录等错误make: *** No rule to make target 'Objects/Engine.cpp.o', needed by 'App'. Stop.
。
解决方案
在模式规则中,词干(与 匹配的部分%
)在目标和先决条件中将是相同的。因此,如果您的目标是,./Objects/foo.o
那么词干是foo
,前提是foo.cpp
。
但是,您没有foo.cpp
,因此该规则不匹配。Make 找不到任何其他匹配的规则,因此它说它不知道如何构建该目标。
仅仅因为您可能有其他文件,例如some/subdir/foo.cpp
,并不意味着它不是在寻找那个文件,而是在寻找foo.cpp
.
一般来说,从许多不同的目录中获取源文件并将构建输出全部放到同一个目录中并不是 make 想要的工作方式(此外,这通常是一个坏主意;如果你不小心创建了两个不同的源文件,会发生什么情况?在两个不同的目录中命名?)
但是,make 确实提供了一个可以使这项工作发挥作用的功能:VPATH
允许 make 在其他目录中搜索源文件。如果你在你的 makefile 中使用它:
SrcFiles := $(shell find . -name "*.cpp")
SrcFileDirs := $(sort $(dir $(SrcFiles))
VPATH := $(SrcFileDirs)
那么它应该可以工作(您应该始终使用:=
with$(shell ...)
来提高效率)。
推荐阅读
- javascript - 无法使用 map() 方法在 React JS 上循环状态
- python - 设置 Treeview 的 rowheight 会使其他小部件在网格中不可见。为什么会发生这种情况
- wordpress - 更改插件设计 wp-crowdfunding
- visual-studio-code - 当我从 GUI 单击运行/调试时,如何强制 VSCode 使用特定终端?
- javascript - Oracle HRMS 如何获取职位的完整描述?
- visual-studio-code - 有没有办法在调试时直接查看字符串的值?(VS代码)
- python - ValueError:试图将“张量”转换为张量并失败。错误:无法创建内容大于 2GB 的张量原型
- c - 谁能解释以下程序的输出
- javascript - algoliaserach 钉合下一页,偏移页
- sql - 消息 206,级别 16,状态 2,第 1 行操作数类型冲突:文本与 tinyint 不兼容