You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Make编译子目录指定文件并输出至obj文件夹?

问题解决:Makefile编译子目录文件报错修复

错误原因

你的编译命令报错是因为使用-c参数时传入了多个源文件,同时指定了单个-o输出文件。gcc的-c参数要求每个源文件单独生成对应的目标文件,不能将多个源文件编译输出到同一个.o文件中。

问题出在你的编译规则:

$(BUILD_DIR)/%.o: %.cpp $(TEST_SRCS)
    @echo compiling $^
    $(CC) $(CFLAGS) -c $^ -o $@

这里的$^会展开成当前.cpp文件加上$(TEST_SRCS)的所有文件,导致编译时同时传入main.cpp和under_test/test_code.cpp,触发gcc的错误。


修正后的Makefile配置

以下是符合需求的完整Makefile,支持编译子目录文件并将目标文件输出到./obj目录(保留子目录结构):

TARGET_EXEC ?= unit_test

IDIR = ./include
CC = g++ --std=c++14
CFLAGS = -g -I$(IDIR) -Iunder_test

BUILD_DIR = obj
# 当前目录所有.cpp文件
SRCS = $(wildcard *.cpp)
# 子目录测试文件
TEST_SRCS = under_test/test_code.cpp
# 合并所有需要编译的源文件
ALL_SRCS = $(SRCS) $(TEST_SRCS)
# 生成对应的目标文件路径(保留子目录结构)
OBJ = $(ALL_SRCS:%.cpp=$(BUILD_DIR)/%.o)

LIBS = -lgtest -lgmock

all: $(TARGET_EXEC)

$(TARGET_EXEC): $(OBJ)
    @echo linking $^
    $(CC) $(OBJ) -o $@ $(CFLAGS) $(LIBS)

# 通用编译规则:自动创建目标文件所在子目录,单个源文件编译
$(BUILD_DIR)/%.o: %.cpp
    @mkdir -p $(dir $@)
    @echo compiling $<
    $(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean show

SOURCES := $(shell basename -a under_test/test_code.cpp \
                                under_test/more_test_code.cpp)

show:
    echo $(SOURCES)

clean:
    rm -rf $(BUILD_DIR)
    rm -f $(TARGET_EXEC) *~ core $(IDIR)/*~

关键修改点

  1. 合并源文件列表:将SRCS和TEST_SRCS合并为ALL_SRCS,确保所有需要编译的文件都被纳入构建流程。
  2. 目标文件路径生成:通过$(ALL_SRCS:%.cpp=$(BUILD_DIR)/%.o)保留源文件的子目录结构,比如under_test/test_code.cpp会生成obj/under_test/test_code.o。
  3. 修复编译规则:
    • 使用$<代替$^,只取当前单个源文件作为编译输入。
    • 添加mkdir -p $(dir $@)自动创建目标文件所需的子目录,避免目录不存在的错误。
  4. 优化清理规则:使用rm -rf $(BUILD_DIR)彻底删除整个obj目录,包括子目录和其中的目标文件。

内容的提问来源于stack exchange,提问作者alicevirgin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 13:45:58