《搭建小智AI对话盒子》系列之一:MacOS下ESP-IDF环境搭建,子模块补齐破局
前言
AI 硬件这两年很热,但身边真正从一块裸板开始,自己焊、自己烧、自己调通一个能对话的 AI 设备的人,少之又少。原因无非是:环境搭建劝退、子模块下载卡死、Python 版本打架、引脚对不上……
本系列文章将基于我自己的实跑经历(一块 ESP32-S3、喇叭、麦克风,最终跑通小智固件,给孩子讲睡前故事),把从环境到成品的完整过程拆成若干篇写下来。本系列设计每篇聚焦一个难点,贴关键命令、与大家探讨一下原理、附实测结果,确保真实可复现验证,且知道为什么这样设计。
本文是系列第一篇,聚焦最劝退但也最该先搞定的:MacOS 下的 ESP-IDF 环境搭建,尤其是子模块卡死这个坑。

一、目标与前置
我想要的是一块 ESP32-S3 开发板,接上喇叭和麦克风,跑一套开源的语音对话固件(小智),让它本地或连云做 ASR/LLM/TTS,给孩子讲睡前故事。
在写第一行代码之前,得先把 ESP-IDF(乐鑫官方的 IoT 开发框架)装好。我的环境:
- 硬件:MacBook Air(Apple Silicon / M1 )
- 系统:macOS(shell = zsh)
- 目标板:ESP32-S3(带 PSRAM 版本,如 N16R8)
- ESP-IDF 版本:
v5.3.2(我选了稳定版,没追 main)
二、先说清楚 ESP-IDF 为什么"难装":子模块机制
ESP-IDF 不是一个单独仓库,它是一个主仓库 + 一堆 git submodule(散在 components/ 下,比如 bt、wifi、mbedtls、lwip……)。官方安装命令长这样:
git clone -b v5.3.2 --recursive https://github.com/espressif/esp-idf.git
--recursive 会连带着把几十个子模块一起拉。问题来了:这些子模块的源全在 github.com,在国内终端里经常被卡死或半路断流。我第一次跑这条命令,卡在 lib_esp32 这个蓝牙子模块上,进度条一动不动,等了十几分钟也没动静。
这不是你操作的问题,是网络通道的问题。终端 git 走的是和浏览器不一样的链路,所以后面要用"浏览器下 ZIP"来绕过。
三、实操踩坑与破局
坑 1:git clone --recursive 卡死
破局方式 A(最快,适合只想先跑通例程):跳过子模块检查
如果你暂时只是想编译 hello_world 验证工具链,根本不需要把所有子模块补齐。ESP-IDF 提供了环境变量直接跳过检查:
cd ~/esp/esp-idf/examples/get-started/hello_world
export IDF_SKIP_CHECK_SUBMODULES=1
idf.py set-target esp32s3
idf.py build
5 秒搞定,cmake 不再纠结子模块完整性。代价:用得上蓝牙/BLE 时这个法子不够,得真补。
破局方式 B(彻底解决,手动下载 ZIP 补齐)
我不是只想跑通 helloworld,我想配置完整啊!!好难啊——所以走了手动补齐的路。思路是:终端 git 拉不动,就用浏览器(可挂代理)把 ZIP 下下来,再塞进对应目录。
以卡住的 lib_esp32 为例:
# 1. 先查这个子模块在 .gitmodules 里的真实地址
cd ~/esp/esp-idf
grep -A 3 "lib_esp32" .gitmodules
# 输出类似:
# [submodule "components/bt/controller/lib_esp32"]
# path = components/bt/controller/lib_esp32
# url = https://github.com/espressif/esp32-bt-lib.git
# 2. 浏览器打开上面的 url(注意不是主仓库!),Code → Download ZIP
# 3. 解压并进目录替换
cd ~/esp/esp-idf/components/bt/controller
rm -rf lib_esp32
unzip ~/Downloads/esp32-bt-lib-*.zip
mv esp32-bt-lib-* lib_esp32
坑 1.5:解压进去后 cmake 还是说子模块缺失**
光放文件不够。ZIP 解出来没有 .git,cmake 检查子模块完整性时依然认为它"没拉全"。得把这个子模块从 git 的 submodule 检查里移除:
cd ~/esp/esp-idf
git config -f .gitmodules --remove-section submodule.components/bt/controller/lib_esp32
git add .gitmodules
git rm --cached components/bt/controller/lib_esp32 2>/dev/null || true
这步做完,编译就不在它身上卡了。其余卡住的子模块(esp-wifi-lib、esp-protobuf-c、mbedtls 等)照方抓药,逐个浏览器下载、解压、移除检查即可。
小提示:有些仓库在 GitHub 上是
esp32-wifi-lib,.gitmodules里写的却是esp-wifi-lib,直接访问会 404。以你本地.gitmodules里的url字段为准,别照抄网上博客的地址。
坑 2:Python 版本打架(externally-managed + EIM 不认 3.13)
装好 IDF 代码后,要用乐鑫的图形化安装器(EIM,.dmg)来装工具链。这里又踩了 Python 的坑。
我的 Mac 上 python3 默认指向 3.15.x,而 EIM 向导要的是 3.13。直接 pip3 install 还会报经典的 error: externally-managed-environment(macOS 现在禁止裸 pip 改系统 Python)。
正确姿势是用 Homebrew 隔离装一个干净的 3.13,再把路径指给向导:
brew install python@3.13
# 确认装到哪了
brew --prefix python@3.13
# 通常输出:/opt/homebrew/opt/python@3.13
# 在 EIM 向导的"高级设置"里,手动指定解释器路径:
# /opt/homebrew/opt/python@3.13/bin/python3.13
如果终端里 python3 --version 仍显示旧版本,临时把它提前:
export PATH="/opt/homebrew/opt/python@3.13/bin:$PATH"
别直接把
export.sh写死进.zshrc全局加载,会拖慢每个终端、还可能和你别的 Python 项目打架。用别名按需激活更稳。
坑 3:get_idf 别名配置
工具链装完后,配置按需激活的别名(只贴关键命令,原理见官方文档):
echo "alias get_idf='. \$HOME/esp/esp-idf/export.sh'" >> ~/.zshrc
source ~/.zshrc
get_idf # 激活 ESP-IDF 环境
四、环境配置清单(实测可复现)
主机: MacBook Air,Apple Silicon
系统: macOS,shell = zsh
目标板: ESP32-S3(带 PSRAM)
ESP-IDF: v5.3.2(手动补齐子模块)
Python: 3.13(Homebrew 隔离,非系统默认)
五、验证:环境真的好了吗
新开终端,激活后跑一条:
get_idf
ls ~/esp/esp-idf/export.sh # 能看到文件 = IDF 本体就位
idf.py --version # 能输出版本 = 工具链通了
看到版本号,说明最难的"环境搭建"这关过了。后面才是硬件接线、音频、固件的事——那些坑更大,下一篇接着写。
小结
如果你也在 Mac 上折腾 ESP32,欢迎在评论区留下你的评论。
更多推荐




所有评论(0)