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

Makefile中for循环无法正常运行问题排查及可移植写法咨询

问题原因分析

这个问题我之前排查过类似的,其实根源不在GNU Make的版本差异,而是Debian系统默认shell的变更导致的:

  • 在Debian旧稳定版(比如Jessie)中,/bin/sh是直接链接到bash的,bash支持自己特有的大括号扩展语法(也就是{20..50000..10}这种生成序列的写法)。
  • 而Debian稳定版(比如Stretch及之后)把/bin/sh默认指向了dash——这是一个轻量的POSIX兼容shell,它不支持bash的大括号扩展特性。
  • GNU Make默认会调用系统的/bin/sh来执行规则里的shell命令,所以在新系统里,dash不认识{20..50000..10},就直接把它当成普通字符串输出了。你提到的Make 4.0 vs 4.1只是刚好和Debian版本升级同步,并不是直接原因。
可移植的实现方式

下面几种方法都能让你的循环在不同Debian版本(或其他POSIX系统)下正常工作:

1. 强制Make使用bash执行命令

在Makefile的最开头加上这一行,指定Make用bash来处理shell命令,这样大括号扩展就能正常生效:

SHELL := /bin/bash

注意:这个方案要求目标系统必须安装bash(Debian系一般都自带,但极简系统或部分小众发行版可能需要提前安装)。

2. 使用POSIX兼容的seq命令

如果想要完全兼容所有POSIX shell,就用seq命令生成序列,替换bash特有的大括号扩展:

all:
	for i in $$(seq 20 10 50000); do \
		echo "Computing $$i"; \
	done

seq的语法是seq 起始值 步长 结束值,所有POSIX兼容系统都支持这个命令,完全不用担心shell兼容性问题。

3. 用Make自身的循环逻辑(脱离shell)

如果不想依赖shell的循环特性,也可以用Make内置的foreach函数实现,完全由Make控制流程:

# 先生成数字序列
NUMBERS := $(shell seq 20 10 50000)
all:
	$(foreach i,$(NUMBERS),echo "Computing $(i)";)

这种方式的好处是不依赖任何shell特性,完全由Make处理,但要注意:所有echo命令会被展开成一行执行,如果你的循环里有更复杂的逻辑(比如需要每条命令单独执行、有依赖关系),可能需要调整写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:33:24