You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

GNU Make 3.82适配:无.c文件时从.s生成.o的规则兼容问题

解决GNU Make 3.82中.s文件生成.o的规则冲突问题

这个问题我之前也碰到过,核心原因是GNU Make 3.82对隐式规则的搜索逻辑做了调整:当你定义了%.c → %.s%.s → %.o两条模式规则时,3.82版本会优先尝试走完整的c→s→o依赖链——哪怕你已经有现成的.s文件,它还是会去检查对应的.c文件是否存在,找不到就直接报错。而3.81版本则会跳过这条无效的链,直接用已有的.s文件生成.o

这里有几个实用的修复方案,你可以根据自己的Makefile结构选择:

方案1:将.c→.s规则改为静态模式(推荐)

把全局的%.s: %.c模式规则,改成只针对你真正需要从.c生成.s的文件。比如你有一个CSRCS变量存放所有.c源文件,就可以这样写:

# 假设CSRCS是你的.c源文件列表
$(CSRCS:.c=.s): %.s: %.c
	$(CC) $(CFLAGS) -o $@ -S $<

%.o: %.s
	$(CC) $(CFLAGS) -o $@ -c $<

all:: $(OBJS)

这样这条规则只会作用于有对应.c文件的.s目标,当没有.c文件时,make不会触发这条规则,自然就会直接用现成的.s文件生成.o了。

方案2:显式处理.s对应的.o文件

先找出所有已存在的.s文件,为它们对应的.o单独定义规则,剩下的.o再用常规规则处理:

# 找出当前目录下所有.s文件,转换成对应的.o文件名
S_OBJS := $(patsubst %.s,%.o,$(wildcard *.s))

# 为这些.o文件单独定义从.s生成的规则
$(S_OBJS): %.o: %.s
	$(CC) $(CFLAGS) -o $@ -c $<

# 剩下的.o文件用.c生成(如果需要的话)
C_OBJS := $(filter-out $(S_OBJS),$(OBJS))
$(C_OBJS): %.o: %.c
	$(CC) $(CFLAGS) -o $@ -c $<

all:: $(OBJS)

这种方式更直白,直接告诉make哪些.o要从.s生成,彻底避免了隐式规则的冲突。

方案3:标记.s文件为非中间文件

通过.NOTINTERMEDIATE告诉make,.s文件是最终文件,不要把它们当作需要生成的中间文件:

# 把所有OBJS对应的.s文件标记为非中间文件
.NOTINTERMEDIATE: $(OBJS:.o=.s)

%.s: %.c
	$(CC) $(CFLAGS) -o $@ -S $<

%.o: %.s
	$(CC) $(CFLAGS) -o $@ -c $<

all:: $(OBJS)

这样make就不会试图去生成这些.s文件,只会直接使用已有的文件来构建.o

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

火山引擎 最新活动