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

编写Makefile实现单源文件生成带架构后缀二进制文件报错

问题排查:Makefile无法生成带架构后缀的二进制文件

需求与问题背景

需要将目录中所有C/C++源文件编译为二进制文件,要求文件名格式为「源文件basename+架构后缀」。编写的Makefile如下:

CC = gcc
CPP = g++
CFLAGS = -std=c89 -std=c99 -fpermissive
CPPFLAGS = -std=c++17 -fpermissive
BINDIR = ./bin

LIBS = -lm
ARCH = $(shell uname -m)

# 收集所有C/C++源文件
SRCS=$(wildcard *.c) 
CPP_SRCS=$(wildcard *.cpp)

# 生成带架构后缀的目标文件列表
OBJS := $(patsubst %.c, $(BINDIR)/%-$(ARCH), $(SRCS))
OBJS += $(patsubst %.cpp, $(BINDIR)/%-$(ARCH), $(CPP_SRCS))

all: $(OBJS)

# C++源文件编译规则
$(BINDIR)/% : %.cpp Makefile
    $(CPP) -o $@ $< $(CPPFLAGS)

# C源文件编译规则
$(BINDIR)/% : %.c Makefile
    $(CC) -o $@ $< $(CFLAGS) $(LIBS)

执行时触发错误:

make: *** No rule to make target `bin/file1-arm64', needed by `all'.  Stop.

问题根源

当前的模式规则$(BINDIR)/% : %.cpp和$(BINDIR)/% : %.c无法匹配目标bin/file1-arm64:

  • 模式中的%会匹配file1-arm64,但对应的源文件是file1.cpp或file1.c,两者名称结构不对应——规则没有处理目标里的-$(ARCH)后缀部分,导致Make找不到生成目标的有效方法。

修复方案

方案一:使用静态模式规则(推荐)

静态模式规则可以精准关联带后缀的目标和对应的源文件,同时补充目录生成规则避免报错:

CC = gcc
CPP = g++
CFLAGS = -std=c99 -fpermissive  # 注:不可同时指定-std=c89和c99,保留c99即可
CPPFLAGS = -std=c++17 -fpermissive
BINDIR = ./bin

LIBS = -lm
ARCH = $(shell uname -m)

SRCS=$(wildcard *.c) 
CPP_SRCS=$(wildcard *.cpp)

OBJS := $(patsubst %.c, $(BINDIR)/%-$(ARCH), $(SRCS))
OBJS += $(patsubst %.cpp, $(BINDIR)/%-$(ARCH), $(CPP_SRCS))

all: $(OBJS)

# 确保输出目录存在
$(BINDIR):
	mkdir -p $(BINDIR)

# C源文件编译规则:匹配bin/xxx-架构 → xxx.c
$(OBJS): $(BINDIR)/%-$(ARCH): %.c $(BINDIR)
	$(CC) -o $@ $< $(CFLAGS) $(LIBS)

# C++源文件编译规则:匹配bin/xxx-架构 → xxx.cpp
$(OBJS): $(BINDIR)/%-$(ARCH): %.cpp $(BINDIR)
	$(CPP) -o $@ $< $(CPPFLAGS)

方案二:普通模式规则结合字符串处理

如果偏好普通模式规则,可以通过字符串截取提取源文件basename,再匹配对应源文件:

CC = gcc
CPP = g++
CFLAGS = -std=c99 -fpermissive
CPPFLAGS = -std=c++17 -fpermissive
BINDIR = ./bin

LIBS = -lm
ARCH = $(shell uname -m)
ARCH_SUFFIX = -$(ARCH)

SRCS=$(wildcard *.c) 
CPP_SRCS=$(wildcard *.cpp)

OBJS := $(patsubst %.c, $(BINDIR)/%-$(ARCH), $(SRCS))
OBJS += $(patsubst %.cpp, $(BINDIR)/%-$(ARCH), $(CPP_SRCS))

all: $(OBJS)

$(BINDIR):
	mkdir -p $(BINDIR)

# 通用编译规则:移除目标的架构后缀,匹配对应源文件
$(BINDIR)/%: $(BINDIR)
	@if [ -f $(subst $(ARCH_SUFFIX),,$*).c ]; then \
		$(CC) -o $@ $(subst $(ARCH_SUFFIX),,$*).c $(CFLAGS) $(LIBS); \
	elif [ -f $(subst $(ARCH_SUFFIX),,$*).cpp ]; then \
		$(CPP) -o $@ $(subst $(ARCH_SUFFIX),,$*).cpp $(CPPFLAGS); \
	fi

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:34:58