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

编写构建源码与对应单元测试的Makefile及架构合理性咨询

嗨,我来帮你搞定这个Makefile的问题,顺便聊聊分不分开的事儿~

首先,先修正你原来主程序Makefile里的一个小错误:你写的objs = $(src:.c=.o)是把.c后缀改成.o,但你的源文件都是.cpp,所以应该改成$(src:.cpp=.o),不然编译的时候会找不到正确的目标文件。

接下来是整合主程序和测试的完整Makefile,既能构建主程序stuff,又能自动生成每个单独的测试程序,还能处理test_all:

# 主程序相关配置
src = $(shell find src -name "*.cpp")
objs = $(src:.cpp=.o)
bin = stuff

# 测试程序相关配置
test_src = $(shell find tests -name "test_*.cpp")
test_bins = $(test_src:.cpp=)  # 把tests/a/test_foo.cpp转成tests/a/test_foo

# 默认目标:构建主程序+所有测试
all: $(bin) $(test_bins)

# 主程序构建规则
$(bin): $(objs)
	$(CXX) -o $@ $^ $(LDFLAGS)

# 单个测试的通用规则:自动匹配test_*.cpp和对应的src文件
# 比如tests/a/test_foo.cpp会自动关联src/a/foo.cpp
$(test_bins): %: %.cpp $(subst test_,,$(subst tests/,src/,$@)).cpp
	$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)

# test_all单独处理:复用主程序的所有目标文件,避免重复编译src代码
tests/test_all: tests/test_all.cpp $(objs)
	$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)

# 通用编译规则:把.cpp编译成.o
%.o: %.cpp
	$(CXX) -c $< -o $@ $(CXXFLAGS)

# 清理所有生成文件
clean:
	rm -f $(bin) $(objs) $(test_bins)

这个Makefile的好处是:

  • 自动发现所有src和tests里的cpp文件,不用手动添加
  • 单个测试只会编译自己和对应的src文件,比如make tests/a/test_foo就只编译test_foo.cpp和src/a/foo.cpp
  • test_all会复用主程序已经编译好的目标文件,节省编译时间
  • 支持标准的make all、make clean,还有单独构建某个测试或主程序

然后来说说分开Makefile是否合理:
这完全取决于你的项目规模和复杂度:

  • 如果是像现在这样的小型项目,把主程序和测试放在同一个Makefile里更方便,不用切换文件,一条命令就能搞定所有构建。
  • 如果项目后续变大,比如src目录结构越来越复杂,测试需要引入额外的依赖(比如gtest、gmock),或者测试的编译配置和主程序差异很大,那分开成两个Makefile(比如根目录的Makefile负责主程序,tests/Makefile负责测试)会更清晰,职责分离,维护起来更简单。

如果选择分开的话,根目录的Makefile可以通过make -C tests来调用测试目录的构建,还能传递编译参数(比如CXX、CXXFLAGS),甚至共享主程序的目标文件(比如把主程序的目标文件放到统一的build/src目录,测试Makefile直接引用),避免重复编译。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:32:54