English version (recommended)
Title: Compilation fails on Windows: sdcc.sh uses bash syntax but is executed by busybox ash (POSIX shell)
Environment
- OS: Windows 10 / Windows 11
- Board package: DeqingSun/ch55xduino (CH55xDuino)
- Tool version:
packages/CH55xDuino/tools/MCS51Tools/2026.07.10
- Core:
hardware/mcs51/0.0.26
- Board: CH552 (any CH55x board)
- Arduino build defines observed:
Arduino IDE 2.3.10
Describe the bug
On Windows, building any sketch fails during the "Detecting libraries included by …" / "Generating function prototypes" stage. The SDCC wrapper sdcc.sh is launched through busybox ash, which is a POSIX shell and does not understand the bash-only syntax used inside the script.
Steps to reproduce
- Install the CH55xDuino board package on Windows.
- Select a board such as CH552.
- Compile any sketch (e.g. a bundled example, or a user sketch like
Serial2USBHIDKey).
- The build aborts with a compilation error.
Expected behavior
The sketch should compile and link successfully.
Actual behavior
The compiler output ends with:
... \MCS51Tools\2026.07.10/win/busybox ash ...\wrapper/sdcc.sh ...\USBhandler.c nul re12 -c -Ddouble=float ... -MMD -MF ...\USBhandler.c.libsdetect.d
Error while detecting libraries included by ...\USBhandler.c
Generating function prototypes...
... \wrapper/sdcc.sh: line 94: syntax error: unexpected "(" (expecting "fi")
... \wrapper/sdcc.sh: line 94: syntax error: unexpected "(" (expecting "fi")
exit status 2
Compilation error: exit status 2
Root cause
On Windows the build recipe invokes the wrapper as:
.../win/busybox ash .../wrapper/sdcc.sh <args...>
so it is interpreted by busybox ash (the Almquist shell, POSIX-only). However sdcc.sh relies on several bashisms:
- Array assignment
FILTERED_ARGS=() and FILTERED_ARGS+=("$arg") in the re12 branch (lines 94 / 107). ash has no arrays → syntax error: unexpected "(" (expecting "fi").
- Extended test
[[ … ]] (lines 144, 153, 166, 167, 181, 194, 195, 209, 210).
== inside a [ … ] test (lines 16, 19); POSIX [ uses =.
On Linux/macOS the #!/bin/bash shebang is honoured so it works; on Windows the explicit busybox ash call bypasses the shebang, so it breaks. The script has therefore never compiled successfully on Windows.
Proposed fix
Make sdcc.sh POSIX sh compatible so it runs under both bash and busybox ash, without changing behavior on other platforms:
- Replace the
FILTERED_ARGS array in the re12 branch with a positional-parameter rebuild: snapshot "$@" into a newline-joined string, filter it with set -f + IFS set to newline, then rebuild $@ via set --. The re12 branch must still drop -c, -MMD, and -MF together with its following argument.
- Replace every
[[ … ]] with [ … ]. For the [[ $(sed --version 2>/dev/null) != *GNU* ]] glob test, use a case statement instead.
- Change
== to = inside [ … ] tests.
After these changes both busybox ash -n sdcc.sh and bash -n sdcc.sh pass, and the re12 flag-filtering behaves correctly (verified: input -c -Ddouble=float -DUSE_STDINT -MMD -MF dep.d -IC:/inc → output -Ddouble=float -DUSE_STDINT -IC:/inc).
Additional context
The re12 branch was added for Arduino CLI ≥ 1.5 library detection / prototype generation (it strips the gcc-style -MMD/-MF flags that SDCC does not handle the same way). A minimal patch that keeps the existing logic but removes the bashisms fixes the Windows failure. A working POSIX rewrite of the re12 branch looks like:
if [ "$MARK" = "re12" ]; then
__saved=""
__first=1
for __arg in "$@"; do
if [ $__first -eq 1 ]; then
__saved="$__arg"; __first=0
else
__saved="$__saved
$__arg"
fi
done
set --
set -f
__skip=0
IFS='
'
for __arg in $__saved; do
if [ $__skip -eq 1 ]; then __skip=0; continue; fi
case "$__arg" in
-c|-MMD) continue ;;
-MF) __skip=1; continue ;;
esac
set -- "$@" "$__arg"
done
unset IFS
set +f
case "$SRC" in
*.cpp.merged) "$SDCC" "$@" -x c "$SRC" -o "$OBJ"; exit $? ;;
*.cpp) "$SDCC" "$@" -x c --include dummy_variable_main.h "$SRC" -o "$OBJ"; exit $? ;;
*.c) "$SDCC" "$@" "$SRC" -o "$OBJ"; exit $? ;;
esac
exit 1
fi
中文版
标题: Windows 下编译失败:sdcc.sh 使用了 bash 语法,但被 busybox ash(POSIX shell)执行
环境
- 操作系统:Windows 10 / Windows 11
- 板卡包:DeqingSun/ch55xduino(CH55xDuino)
- 工具版本:
packages/CH55xDuino/tools/MCS51Tools/2026.07.10
- 核心:
hardware/mcs51/0.0.26
- 开发板:CH552(任意 CH55x 板)
- 编译时可见的宏定义:
Arduino IDE 2.3.10
问题描述
在 Windows 上,编译任意工程都会在执行「Detecting libraries included by …」/「Generating function prototypes」阶段失败。SDCC 的封装脚本 sdcc.sh 是通过 busybox ash 调用的,而 busybox ash 是 POSIX shell,不支持脚本里使用的 bash 专有语法。
复现步骤
- 在 Windows 上安装 CH55xDuino 板卡包。
- 选择 CH552 等开发板。
- 编译任意工程(例如自带示例,或用户工程
Serial2USBHIDKey)。
- 编译中断并报错。
预期行为
工程应正常编译、链接通过。
实际行为
编译器输出以如下内容结束:
... \MCS51Tools\2026.07.10/win/busybox ash ...\wrapper/sdcc.sh ...\USBhandler.c nul re12 -c -Ddouble=float ... -MMD -MF ...\USBhandler.c.libsdetect.d
Error while detecting libraries included by ...\USBhandler.c
Generating function prototypes...
... \wrapper/sdcc.sh: line 94: syntax error: unexpected "(" (expecting "fi")
... \wrapper/sdcc.sh: line 94: syntax error: unexpected "(" (expecting "fi")
exit status 2
Compilation error: exit status 2
根因
Windows 上构建命令实际是这样调用封装脚本的:
.../win/busybox ash .../wrapper/sdcc.sh <参数...>
也就是说它由 busybox ash(Almquist shell,仅 POSIX)来解释执行。但 sdcc.sh 里用了若干 bash 特性:
re12 分支里的数组赋值 FILTERED_ARGS=() 与 FILTERED_ARGS+=("$arg")(第 94 / 107 行)。ash 不支持数组 → 报 syntax error: unexpected "(" (expecting "fi")。
- 扩展测试
[[ … ]](第 144、153、166、167、181、194、195、209、210 行)。
[ … ] 测试里用了 ==(第 16、19 行);POSIX 的 [ 应该用 =。
在 Linux/macOS 上 #!/bin/bash 这行 shebang 会生效,所以能正常跑;在 Windows 上显式用 busybox ash 调用绕过了 shebang,于是整体崩溃。该脚本在 Windows 上其实从未成功编译过。
建议修复
把 sdcc.sh 改写为 POSIX sh 兼容,使其在 bash 和 busybox ash 下都能运行,且不改变其他平台的行为:
- 将
re12 分支里的 FILTERED_ARGS 数组改为「重建位置参数」:先把 "$@" 快照成一个以换行连接的字符串,用 set -f + 把 IFS 设为换行来遍历过滤,再用 set -- 重建 $@。re12 分支仍需丢弃 -c、-MMD,以及 -MF 和它后面的那个参数。
- 把每个
[[ … ]] 替换为 [ … ]。其中 [[ $(sed --version 2>/dev/null) != *GNU* ]] 这种通配符匹配改用 case 语句实现。
- 把
[ … ] 测试里的 == 改为 =。
修改后 busybox ash -n sdcc.sh 与 bash -n sdcc.sh 均通过,且 re12 的过滤逻辑正确(已验证:输入 -c -Ddouble=float -DUSE_STDINT -MMD -MF dep.d -IC:/inc → 输出 -Ddouble=float -DUSE_STDINT -IC:/inc)。
补充说明
re12 分支是为 Arduino CLI ≥ 1.5 的库探测/函数原型生成而加的(它去掉 SDCC 不支持的同名 gcc 风格 -MMD/-MF 参数)。只要保留原有逻辑、去掉 bash 特性,就能修复 Windows 上的失败。可用的 POSIX 版 re12 分支示例如下:
if [ "$MARK" = "re12" ]; then
__saved=""
__first=1
for __arg in "$@"; do
if [ $__first -eq 1 ]; then
__saved="$__arg"; __first=0
else
__saved="$__saved
$__arg"
fi
done
set --
set -f
__skip=0
IFS='
'
for __arg in $__saved; do
if [ $__skip -eq 1 ]; then __skip=0; continue; fi
case "$__arg" in
-c|-MMD) continue ;;
-MF) __skip=1; continue ;;
esac
set -- "$@" "$__arg"
done
unset IFS
set +f
case "$SRC" in
*.cpp.merged) "$SDCC" "$@" -x c "$SRC" -o "$OBJ"; exit $? ;;
*.cpp) "$SDCC" "$@" -x c --include dummy_variable_main.h "$SRC" -o "$OBJ"; exit $? ;;
*.c) "$SDCC" "$@" "$SRC" -o "$OBJ"; exit $? ;;
esac
exit 1
fi
sdcc.sh
English version (recommended)
Title: Compilation fails on Windows:
sdcc.shuses bash syntax but is executed bybusybox ash(POSIX shell)Environment
packages/CH55xDuino/tools/MCS51Tools/2026.07.10hardware/mcs51/0.0.26Arduino IDE 2.3.10Describe the bug
On Windows, building any sketch fails during the "Detecting libraries included by …" / "Generating function prototypes" stage. The SDCC wrapper
sdcc.shis launched throughbusybox ash, which is a POSIX shell and does not understand the bash-only syntax used inside the script.Steps to reproduce
Serial2USBHIDKey).Expected behavior
The sketch should compile and link successfully.
Actual behavior
The compiler output ends with:
Root cause
On Windows the build recipe invokes the wrapper as:
so it is interpreted by
busybox ash(the Almquist shell, POSIX-only). Howeversdcc.shrelies on several bashisms:FILTERED_ARGS=()andFILTERED_ARGS+=("$arg")in there12branch (lines 94 / 107).ashhas no arrays →syntax error: unexpected "(" (expecting "fi").[[ … ]](lines 144, 153, 166, 167, 181, 194, 195, 209, 210).==inside a[ … ]test (lines 16, 19); POSIX[uses=.On Linux/macOS the
#!/bin/bashshebang is honoured so it works; on Windows the explicitbusybox ashcall bypasses the shebang, so it breaks. The script has therefore never compiled successfully on Windows.Proposed fix
Make
sdcc.shPOSIXshcompatible so it runs under bothbashandbusybox ash, without changing behavior on other platforms:FILTERED_ARGSarray in there12branch with a positional-parameter rebuild: snapshot"$@"into a newline-joined string, filter it withset -f+IFSset to newline, then rebuild$@viaset --. There12branch must still drop-c,-MMD, and-MFtogether with its following argument.[[ … ]]with[ … ]. For the[[ $(sed --version 2>/dev/null) != *GNU* ]]glob test, use acasestatement instead.==to=inside[ … ]tests.After these changes both
busybox ash -n sdcc.shandbash -n sdcc.shpass, and there12flag-filtering behaves correctly (verified: input-c -Ddouble=float -DUSE_STDINT -MMD -MF dep.d -IC:/inc→ output-Ddouble=float -DUSE_STDINT -IC:/inc).Additional context
The
re12branch was added for Arduino CLI ≥ 1.5 library detection / prototype generation (it strips the gcc-style-MMD/-MFflags that SDCC does not handle the same way). A minimal patch that keeps the existing logic but removes the bashisms fixes the Windows failure. A working POSIX rewrite of there12branch looks like:中文版
标题: Windows 下编译失败:
sdcc.sh使用了 bash 语法,但被busybox ash(POSIX shell)执行环境
packages/CH55xDuino/tools/MCS51Tools/2026.07.10hardware/mcs51/0.0.26Arduino IDE 2.3.10问题描述
在 Windows 上,编译任意工程都会在执行「Detecting libraries included by …」/「Generating function prototypes」阶段失败。SDCC 的封装脚本
sdcc.sh是通过busybox ash调用的,而busybox ash是 POSIX shell,不支持脚本里使用的 bash 专有语法。复现步骤
Serial2USBHIDKey)。预期行为
工程应正常编译、链接通过。
实际行为
编译器输出以如下内容结束:
根因
Windows 上构建命令实际是这样调用封装脚本的:
也就是说它由
busybox ash(Almquist shell,仅 POSIX)来解释执行。但sdcc.sh里用了若干 bash 特性:re12分支里的数组赋值FILTERED_ARGS=()与FILTERED_ARGS+=("$arg")(第 94 / 107 行)。ash不支持数组 → 报syntax error: unexpected "(" (expecting "fi")。[[ … ]](第 144、153、166、167、181、194、195、209、210 行)。[ … ]测试里用了==(第 16、19 行);POSIX 的[应该用=。在 Linux/macOS 上
#!/bin/bash这行 shebang 会生效,所以能正常跑;在 Windows 上显式用busybox ash调用绕过了 shebang,于是整体崩溃。该脚本在 Windows 上其实从未成功编译过。建议修复
把
sdcc.sh改写为 POSIXsh兼容,使其在bash和busybox ash下都能运行,且不改变其他平台的行为:re12分支里的FILTERED_ARGS数组改为「重建位置参数」:先把"$@"快照成一个以换行连接的字符串,用set -f+ 把IFS设为换行来遍历过滤,再用set --重建$@。re12分支仍需丢弃-c、-MMD,以及-MF和它后面的那个参数。[[ … ]]替换为[ … ]。其中[[ $(sed --version 2>/dev/null) != *GNU* ]]这种通配符匹配改用case语句实现。[ … ]测试里的==改为=。修改后
busybox ash -n sdcc.sh与bash -n sdcc.sh均通过,且re12的过滤逻辑正确(已验证:输入-c -Ddouble=float -DUSE_STDINT -MMD -MF dep.d -IC:/inc→ 输出-Ddouble=float -DUSE_STDINT -IC:/inc)。补充说明
re12分支是为 Arduino CLI ≥ 1.5 的库探测/函数原型生成而加的(它去掉 SDCC 不支持的同名 gcc 风格-MMD/-MF参数)。只要保留原有逻辑、去掉 bash 特性,就能修复 Windows 上的失败。可用的 POSIX 版re12分支示例如下:sdcc.sh