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

如何编写含头文件依赖的Makefile?用g++编译生成可执行文件

解决你的Makefile编译问题

我来帮你一步步搞定这些Makefile的坑,先直接给你能正常工作的版本,再解释每个部分对应解决你的问题:

# 定义编译器和编译标准
CXX = g++
CXXFLAGS = -std=gnu++17

# 最终要生成的可执行文件名称
TARGET = create-exercise

# 项目里的C++源文件(只放.cpp,.hpp是依赖不是编译输入)
SOURCES = create-exercise.cpp

# 自动推导对应的目标文件(每个.cpp生成一个.o)
OBJECTS = $(SOURCES:.cpp=.o)

# 默认执行的目标:生成可执行文件
all: $(TARGET)

# 链接生成可执行文件:依赖是所有编译好的.o文件
$(TARGET): $(OBJECTS)
	$(CXX) $(CXXFLAGS) $^ -o $@

# 编译单个.cpp到.o:每个.o依赖对应的.cpp和exercise.hpp
%.o: %.cpp exercise.hpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# 清理生成的中间文件和可执行文件
clean:
	rm -f $(OBJECTS) $(TARGET)

接下来逐个解决你遇到的问题:

问题1:把exercise.hpp加入依赖后被当成编译输入

你之前应该是把.hpp直接放到了可执行文件的依赖里,然后用$^(所有依赖)传给g++,导致g把.hpp也当成了要编译的源文件。现在我们把.hpp放到目标文件(.o)的依赖里,编译.o的时候只用$<(第一个依赖,也就是对应的.cpp文件)作为输入,这样g就不会处理.hpp文件了——毕竟.hpp已经被.cpp包含进去了,不需要单独编译。

问题2:生成.o时自动加-c导致无法运行

-c参数本来就是用来生成目标文件(.o)的,这是正常的编译步骤——目标文件本身就是不可直接运行的中间产物。我们把流程拆成两步:

  1. 用-c编译.cpp到.o(这一步是编译源码到机器码,但还没链接)
  2. 把所有.o文件链接成可执行文件(这一步不用-c,最终产物就是能直接运行的程序)
    这样就不会出现“生成的文件不能运行”的问题了。

问题3:修改exercise.hpp时Make提示文件已最新

这是因为之前的规则里没有把.hpp作为编译的依赖项,Make不知道.hpp变化需要重新编译。现在我们给.cpp -> .o的规则加上了exercise.hpp作为依赖,只要这个头文件有修改,Make就会自动重新编译对应的.o,然后重新链接成新的可执行文件。

如果之后你添加了更多头文件,只需要把它们加到%.o规则的依赖列表里就行,比如:

%.o: %.cpp exercise.hpp another-header.hpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

现在你只需要在终端运行make就能自动编译,修改头文件或者源文件后再运行make都会自动重新编译对应的部分,运行make clean可以清理生成的文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 16:12:40