首页 > 解决方案 > 特定于目录结构的 Makefile

问题描述

我正在尝试使用 makefile 编译我的项目。我是makefile的新手,所以请原谅我的无知。我遇到的问题是我希望输出命令构建所有 .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

解决方案


这一行:

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

无法按书面方式正常工作。这是做什么的?它告诉 make,目标output(顺便说一句,您从未真正创建过:此规则创建一个完全不同的文件out/recipe_book.out,但暂时将其放在一边)取决于文件main/main.cpp,main/main.hpp和 glob 表达式的扩展obj/*.o。因此,make 查找与 glob 表达式匹配的文件,即所有已存在obj/*.o的目标文件。

如果所有目标文件都已经存在,那么它们都将被链接。如果您还没有创建任何目标文件,那么它们都不会被找到(就像您运行ls obj/*.o没有找到文件一样),因此它们都不会被链接。

您必须在此处列出要链接的明确目标文件集。您不能使用 glob 表达式来查找它们。

您可以使用 glob 表达式查找始终(可能)存在的文件,然后将它们转换为目标文件。也许是这样的:

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中,所有非假目标应该总是有他们创建的实际文件的名称)。


推荐阅读