GNU Make与BSD Make模式规则差异问题及修复咨询
问题描述
在同时安装了gmake(GNU Make)和make(BSD Make)的FreeBSD机器上,运行同一个Makefile时输出日志不一致:
- 使用
gmake的输出:
compile main.cpp linking myout
- 使用
make的输出:
c++ -O2 -pipe -c main.cpp -o main.o linking myout
对应的Makefile内容:
TARGET = myout default: $(TARGET) SRCS = main.cpp OBJS = $(SRCS:%.cpp=%.o) default: $(BIN) %.o: %.cpp @echo compile $< @$(CXX) -c $< -o $@ $(TARGET): $(OBJS) @echo linking $@ @$(CXX) $(OBJS) -o $@ clean: @rm -f $(OBJS) $(TARGET)
差异原因
- 重复定义的默认目标冲突:Makefile中两次定义了
default目标,第一次是default: $(TARGET),第二次是default: $(BIN)。由于BIN变量未定义,BSD Make会判定第二次的default目标无效,转而启用自身内置的.cpp.o编译规则;而GNU Make会优先采用最后定义的default目标,但因BIN不存在,会回退到之前有效的default: $(TARGET),进而触发用户自定义的%.o: %.cpp规则。 - 模式规则优先级差异:GNU Make会优先使用用户自定义的模式规则,而BSD Make在默认目标失效时,会调用内置的C++编译规则——该规则没有
@前缀,因此会直接打印编译命令,同时使用FreeBSD默认的编译参数-O2 -pipe。
修复方案
- 移除重复的默认目标:删除
default: $(BIN)这一行,确保默认目标明确指向$(TARGET),让两个版本的Make都能正确识别构建目标。 - 确保自定义规则被触发:确认
OBJS变量正确生成,且$(TARGET)依赖$(OBJS),强制两个版本的Make都使用用户定义的%.o: %.cpp规则编译目标文件,而非内置规则。
修改后的Makefile示例:
TARGET = myout SRCS = main.cpp OBJS = $(SRCS:%.cpp=%.o) default: $(TARGET) %.o: %.cpp @echo compile $< @$(CXX) -c $< -o $@ $(TARGET): $(OBJS) @echo linking $@ @$(CXX) $(OBJS) -o $@ clean: @rm -f $(OBJS) $(TARGET)
内容的提问来源于stack exchange,提问作者Dexter Gaulin
相关产品推荐
相关产品推荐

