特定于目录结构的Makefile

问题描述 投票:0回答:2

我正在尝试使用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
c++ makefile
2个回答
1
投票

此行:

output: main/main.cpp main/main.hpp $(OBJ)/*.o

无法按照书面规定正常工作。这是做什么的?它告诉make,目标output(顺便说一句,您实际上并未创建:此规则创建了一个完全不同的文件out/recipe_book.out,但暂时将其保留)取决于文件main/main.cppmain/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中,所有非语音目标都应始终使用其创建的实际文件名)。


0
投票

您的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放入其中,而不是对其进行特殊处理。

© www.soinside.com 2019 - 2024. All rights reserved.