我正在尝试使用Makefile编译我的项目。我是makefile的新手,所以可以原谅我的无知。我遇到的问题是,我希望输出命令生成所有.o文件,但是如果以这种方式运行它,则不会生成.o文件,而是尝试在.o文件中编译所有.o文件。 / obj目录。
我将如何在输出规则中编译所有.o文件规则?
The directory structure for this project is:
recipe_book
|-GFX (source directory)
|-PageManager (source directory)
|-Pages (source directory)
|-main (source directory)
|-obj (.o files directory)
|-out (application output)
这是我的Makefile:
#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
COMPILER_FLAGS = -w -g
#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lSDL2 -lSDL2_image
G++ = g++ -std=c++17 $(LINKER_FLAGS) $(COMPILER_FLAGS)
#Source Directories:
GFX := GFX
PAGE_MANAGER := PageManager
PAGES := Pages
#Object Directory:
OBJ := obj
# Complile the objects into the executable
output: main/main.cpp main/main.hpp $(OBJ)/*.o
$(G++) main/main.cpp $(OBJ)/*.o -o out/recipe_book.out
#make all object files
#'.' turns them into macros?
#GFX
$(OBJ)/%.o: $(GFX)/%.cpp $(GFX)/%.hpp
$(G++) -I$(GFX) -c $< -o $@
#PageManager
$(OBJ)/%.o: $(PAGE_MANAGER)/%.cpp $(PAGE_MANAGER)/%.hpp
$(G++) -I$(PAGE_MANAGER) -c $< -o $@
#Pages
$(OBJ)/%.o: $(PAGES)/%.cpp $(PAGES)/%.hpp
$(G++) -I$(PAGES) -c $< -o $@
clean:
rm out/*.out obj/*.o
此行:
output: main/main.cpp main/main.hpp $(OBJ)/*.o
无法按照书面规定正常工作。这是做什么的?它告诉make,目标output
(顺便说一句,您实际上并未创建:此规则创建了一个完全不同的文件out/recipe_book.out
,但暂时将其保留)取决于文件main/main.cpp
,main/main.hpp
,以及全局表达式obj/*.o
的扩展。因此,make查找与全局表达式obj/*.o
匹配的文件,即所有目标文件已经存在。
如果所有目标文件都已经存在,那么将链接所有它们。如果尚未创建任何目标文件,则将不会找到任何目标文件(就像运行ls obj/*.o
时未找到文件一样),因此都将不会链接它们。
您必须在此处列出要链接的对象文件的显式集合。您无法使用全局表达式来查找它们。
您可以使用glob表达式查找一直(大概)存在的source文件,然后将其转换为目标文件。也许像这样:
SOURCES := $(wildcard $(GFX)/*.cpp $(PAGE_MANAGER)/*.cpp $(PAGES)/*.cpp)
OBJECTS := $(addprefix $(OBJ)/,$(patsubst %.cpp,%.o,$(notdir $(SOURCES))))
output: main/main.cpp main/main.hpp $(OBJECTS)
(顺便说一下,您确实应该为此目标使用真实的文件名,而不是output
:在make中,所有非语音目标都应始终使用其创建的实际文件名)。
您的output
目标具有$(OBJ)/*.o
作为先决条件。
但是,当尚未构建任何东西时,该通配符将扩展为零!
您将需要列出项目的最终链接所需的对象,例如
output: main/main.cpp main/main.hpp $(OBJ)/GFX.o $(OBJ)/PageManager.o $(OBJ)/Pages.o
然后将在需要时触发这些文件的创建(通过编译)。
您可以通过将GFX PageManager Pages
放入变量中,然后进行替换以将$(OBJ)/
附加在每个变量之前,并将.o
附加到每个变量来简化它。
顺便说一句,我可能会将main
放入其中,而不是对其进行特殊处理。