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

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)
差异原因
  1. 重复定义的默认目标冲突:Makefile中两次定义了default目标,第一次是default: $(TARGET),第二次是default: $(BIN)。由于BIN变量未定义,BSD Make会判定第二次的default目标无效,转而启用自身内置的.cpp.o编译规则;而GNU Make会优先采用最后定义的default目标,但因BIN不存在,会回退到之前有效的default: $(TARGET),进而触发用户自定义的%.o: %.cpp规则。
  2. 模式规则优先级差异:GNU Make会优先使用用户自定义的模式规则,而BSD Make在默认目标失效时,会调用内置的C++编译规则——该规则没有@前缀,因此会直接打印编译命令,同时使用FreeBSD默认的编译参数-O2 -pipe。
修复方案
  1. 移除重复的默认目标:删除default: $(BIN)这一行,确保默认目标明确指向$(TARGET),让两个版本的Make都能正确识别构建目标。
  2. 确保自定义规则被触发:确认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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:40:57