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

如何编写Makefile实现src目录下各cpp文件独立编译输出到Obj目录

规则含义说明

你最开始写的%: %.cpp是Make的静态模式规则,语法为目标列表: 目标匹配模式: 依赖匹配模式:

  • 规则作用对象是前面列出的$(objects)即test、helloworld两个目标
  • 模式里的%是通配符,会匹配目标名中的任意非空字符串(称为「词干」)
  • 依赖部分的%.cpp会把匹配到的词干代入,自动找同名的.cpp文件作为依赖
    这条规则等价于手动写两条独立规则:
test: test.cpp
        $(CC) $(CFLAGS) -o $@ $<
helloworld: helloworld.cpp
        $(CC) $(CFLAGS) -o $@ $<

你之前以为会先生成.o文件再链接,是混淆了规则优先级:你手写的静态模式规则优先级高于Make内置的隐式编译规则,因此不会走「cpp→o→可执行文件」的流程,直接把源码编译成最终目标。

之前分目录编译失败的核心原因

你写的参考规则出现乱编译、重复覆盖输出文件的问题,本质是三个低级错误:

  1. 没有把all放在Makefile的第一个位置作为默认目标,你写的首个目标是main.exe,如果文件里残留旧规则、或者路径匹配失效,Make会fallback到内置的%.o: %.cpp隐式规则,把当前目录下的.o文件当成构建目标,才会出现所有cpp都编译到同一个helloworld.o的现象
  2. 规则里生成的是.o目标文件,和你预期的.out可执行文件后缀不匹配
  3. 没有提前创建Obj输出目录,输出路径不存在时会导致规则匹配异常、编译报错

符合需求的可用Makefile实现

对应你的目录结构:

  • 源码目录src/下存放Test.cpp、Helloworld.cpp
  • 编译输出到Obj/目录,生成Test.out、Helloworld.out

直接用下面的配置即可:

# 基础编译配置
CC := g++
CFLAGS := -g -Wall
SRC_DIR := src
OBJ_DIR := Obj

# 自动扫描源码,生成对应目标文件列表
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
TARGETS := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.out,$(SRC_FILES))

# 声明伪目标,避免和同名文件冲突
.PHONY: all clean
# 默认目标:编译所有可执行文件
all: $(TARGETS)

# 静态模式规则:逐个编译源码到输出目录
$(TARGETS): $(OBJ_DIR)/%.out: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
	$(CC) $(CFLAGS) -o $@ $<

# 顺序依赖:编译前自动创建输出目录,不会因目录时间戳触发重复编译
$(OBJ_DIR):
	mkdir -p $@

# 清理编译产物
clean:
	rm -rf $(OBJ_DIR)

直接在Makefile所在目录执行make,就会自动创建Obj目录,将两个源码文件分别编译为对应名称的.out可执行文件存入,不会出现规则串扰、重复编译的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:03:23