使用Makefile将C++目标文件输出到App目录时构建失败
C++ Makefile无法将目标文件生成到App目录,构建失败
问题概述
尝试将C++程序的目标文件与可执行文件输出至App独立目录,但构建失败,目标文件未生成到指定目录。
错误信息
make: *** No rule to make the target 'App/src/Player/Player.o', needed by 'build'. Stop.
目录结构
drwxrwxr-x - akashdiphazra 3 Jul 23:17 ├── App (Dir of object and exe files) .rwxrwxr-x 35k akashdiphazra 3 Jul 23:17 │ .rwxrwxr-x 619 akashdiphazra 3 Jul 23:17 ├── Makefile drwxrwxr-x - akashdiphazra 3 Jul 23:17 └── src (Dir) .rwxrwxr-x 205 akashdiphazra 3 Jul 14:29 ├── main.cpp | drwxrwxr-x - akashdiphazra 3 Jul 23:17 └── Player (Dir) .rwxrwxr-x 135 akashdiphazra 3 Jul 14:24 ├── Player.cpp .rwxrwxr-x 284 akashdiphazra 3 Jul 14:24 ├── Player.h
原Makefile代码
CC = g++ CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -pedantic -ggdb EXECUTABLE_NAME = akash MEMORY_SAFE_FLAGS= -fsanitize=address -fno-omit-frame-pointer BUILD_DIR = App CXX_SOURCES = $(wildcard src/*.cpp src/**/*.cpp) CXX_OBJECTS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(CXX_SOURCES)) all: build execute build: $(CXX_OBJECTS) $(CC) $(CXXFLAGS) $(CXX_OBJECTS) $(LDFLAGS) -o $(BUILD_DIR)/$(EXECUTABLE_NAME) execute: ./$(BUILD_DIR)/$(EXECUTABLE_NAME) clean: rm -f $(BUILD_DIR)/*.o $(BUILD_DIR)/%.o : %.cpp $(CC) $(CFLAGS) -c $^ -o $@
问题分析
- 嵌套目录未自动创建:目标文件路径如
App/src/Player/Player.o包含多层子目录,make不会自动创建这些目录,导致无法生成文件。 - 编译参数错误:使用了C语言的
$(CFLAGS)而非C++的$(CXXFLAGS),编译选项缺失可能引发问题。 - clean规则不完整:仅删除
App/*.o,但目标文件实际在App/src及子目录下,无法彻底清理。 - 内存安全标志未在链接阶段使用:定义了
MEMORY_SAFE_FLAGS但未加入链接命令,若启用地址 sanitizer会失效。
修正后的Makefile
CC = g++ CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -pedantic -ggdb EXECUTABLE_NAME = akash MEMORY_SAFE_FLAGS= -fsanitize=address -fno-omit-frame-pointer BUILD_DIR = App # 递归获取所有cpp文件(确保make支持**通配符,若不支持可替换为find src -name "*.cpp") CXX_SOURCES = $(wildcard src/*.cpp src/**/*.cpp) # 转换源文件路径为App目录下的目标文件路径 CXX_OBJECTS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(CXX_SOURCES)) all: build execute build: $(CXX_OBJECTS) $(CC) $(CXXFLAGS) $(MEMORY_SAFE_FLAGS) $(CXX_OBJECTS) $(LDFLAGS) -o $(BUILD_DIR)/$(EXECUTABLE_NAME) execute: ./$(BUILD_DIR)/$(EXECUTABLE_NAME) clean: rm -rf $(BUILD_DIR)/src rm -f $(BUILD_DIR)/$(EXECUTABLE_NAME) # 编译规则:先创建目标文件所在目录,再编译 $(BUILD_DIR)/%.o : %.cpp @mkdir -p $(dir $@) $(CC) $(CXXFLAGS) $(MEMORY_SAFE_FLAGS) -c $< -o $@
关键修改说明
- 自动创建嵌套目录:添加
@mkdir -p $(dir $@),在编译每个目标文件前自动生成其所在的多层目录,避免因目录不存在导致的构建失败。 - 修正编译参数:替换
$(CFLAGS)为$(CXXFLAGS),确保使用C++编译选项。 - 完善clean规则:递归删除
App/src目录清理所有目标文件,同时删除可执行文件。 - 链接阶段加入内存安全标志:将
MEMORY_SAFE_FLAGS添加到链接命令中,确保地址 sanitizer正常工作。 - 优化编译依赖引用:用
$<(第一个依赖文件)代替$^(所有依赖文件),单文件编译更准确。
内容的提问来源于stack exchange,提问作者Akashdip Hazra
相关产品推荐
相关产品推荐

