ESP32 Arduino Core 在 Monterey 12.3 編譯錯誤
Tags: esp32, arduino, macos, monterey
Published: 2022-04-23 07:32:04

如果你是使用 Mac 電腦, 在作業系統升級到 macOS 12.3(Monterey) 或更新的版本後, 會發現要使用 Arduino IDE 編譯 ESP32 的程式會出現以下的錯誤：

![](https://i.imgur.com/dRmjCnZ.png)

這是因為 ESP32 Arduino Core 在連結程式的階段會使用到一個 `gen_esp32part.py` 的 python 程式檔, 但是 macOS 在升級到 12.3 時把[內建的 Python 2.7 拿掉](https://developer.apple.com/documentation/macos-release-notes/macos-12_3-release-notes#Python)了, 所以你會在 Arduino 的訊息窗內看到要執行 python 時找不到這個指令。

## 解法一：安裝 Python 2.7

你可能會想說既然 Python 2.7 被拿掉了, 那我就把 [Python 2.7](https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg) 裝回來就好了。

### 單純安裝 Python 2.7 無法解決問題

不過事情沒有這麼簡單, 由於你自己手動安裝的 Python 2.7 的執行檔 `python` 並不是放在 macOS 舊版本內建 Python 的 `/usr/bin/` 下, 而是在以下的路徑：

```bash
% where python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
/usr/local/bin/python
% ls -l /usr/local/bin/python
lrwxr-xr-x  1 root  wheel  68  4 23 09:11 /usr/local/bin/python -> ../../../Library/Frameworks/Python.framework/Versions/2.7/bin/python
```

由於放置的路徑並不在 macOS 系統預設的 PATH (`/bin`, `/usr/bin`) 中, 因此當 Arduino 要執行 python 時仍然會找不到。

不過因為上述 Python 路徑會被加到 zsh 的 .zprofile 中：

```bash
% cat .zprofile

# Setting PATH for Python 2.7
# The original version is saved in .zprofile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
export PATH
```

所以在終端機中鍵入 `python` 是可以執行的：

```bash
% python
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 19 2020, 20:48:48)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

如果在終端機中使用 `open` 開啟 Arduino, 就可以正常編譯了：

```bash
% open Arduino.app
```

![](https://i.imgur.com/sExtIFl.png)

### 修改 ESP32 套件檔案強制執行特定路徑的 Python

如果可以修改 ESP32 套件的設定, 讓它執行上述路徑下的 python, 就可以解決問題了。以下以 ESP32 Arduino Core 2.0.2 版為例, 要修改的檔案在：

`~/Library/Arduino15/packages/esp32/hardware/esp32/2.0.2/platform.txt`

只要將其中出現 `python` 的地方修改為 `/usr/local/bin/python`, 像是這樣：

```
name=ESP32 Arduino
version=
...

tools.esptool_py.network_cmd=/usr/local/bin/python "{runtime.platform.path}/tools/espota.py" -r
tools.esptool_py.network_cmd.windows="{runtime.platform.path}/tools/espota.exe" -r

tools.gen_esp32part.cmd=/usr/local/bin/python "{runtime.platform.path}/tools/gen_esp32part.py"
...
```

重新執行 Arduino 後就可以正常編譯程式了。

## 解法二：改用內建的 Python 3

前面的解法雖然可行, 不過 macOS 之所以要拿掉 Python 2, 就是因為 Python 官方已經不再支援 Python 2, 而我們故意把 Python 2 裝回來, 好像背道而馳。好消息是, ESP32 套件使用的 python 程式相容於 Python 3, 而且 macOS 其實有支援 Python 3。

### 安裝內建的 Python 3

在 `/usr/bin/` 下有 `python3` 指令, 不過如果你執行它, 會看到它噴出以下的訊息 (如果你執行後看到 Python 3, 表示你之前已經安裝過)：

```bash
% /usr/bin/python3
xcode-select: note: no developer tools were found at '/Applications/Xcode.app', requesting install. Choose an option in the dialog to download the command line developer tools.
```

告訴你需要安裝[命令列開發者工具](https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-HOW_CAN_I_UNINSTALL_THE_COMMAND_LINE_TOOLS_), 同時也會看到如下的視窗：

![](https://i.imgur.com/vI6qq0c.png)

它會安裝相關的命令列工具, 其中就包含有 Python 3.8, 安裝完後 `/usr/bin/python3` 就會執行 Python 3。

要注意的是這個 Python 3 的環境並不會隨官方版本即時更新, 如果你很在意, 建議可以改成安裝 Python 官方提供的版本。

### 修改 ESP32 套件強制使用內建的 Python 3

由於內建的 Python 3 的指令是在 `/usr/bin/`, 包含在系統預設的路徑下, 所以只要修改：

`~/Library/Arduino15/packages/esp32/hardware/esp32/2.0.2/platform.txt`

檔案, 將其中出現 `python` 的地方修改為 `python3`, 像是這樣：

```
name=ESP32 Arduino
version=
...

tools.esptool_py.network_cmd=python3 "{runtime.platform.path}/tools/espota.py" -r
tools.esptool_py.network_cmd.windows="{runtime.platform.path}/tools/espota.exe" -r

tools.gen_esp32part.cmd=python3 "{runtime.platform.path}/tools/gen_esp32part.py"
...
```

不需要指明完整的路徑, 存檔後重新執行 Arduino 就可以正常編譯程式了。

### 官方作法

目前 [ESP32 Arduino Core 開發中版本 2.0.3.RC1](https://github.com/espressif/arduino-esp32/commit/c25feca639fb2936786ec0cb521e14fff5eb5113) 採取的就是這一種解法, 如果你不想自行修改 `platform.txt` 檔案, 也可以透過以下網址安裝開發中版本的 ESP32 套件：

```
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
```

## 解法三：使用 Python 官方的 Python 3

前面有提過, 內建的 Python 3 不會即時隨官方版本更新, 這若是很重要, 就可以改裝 Python [官方的 Python 3](https://www.python.org/ftp/python/3.10.4/python-3.10.4-macos11.pkg)。

### 安裝 Python 官方的 Python 3

這種方式和內建的 Python 3 最重要的差別就是 `python3` 的指令是放在 `/usr/local/bin/` 下, 因此, 稍後修改 ESP32 套件設定檔時要指明完整的路徑。

如果想移除前一種解法安裝的命令列開發者工具, 只要將以下資料夾刪除即可：

```
/Library/Developer/CommandLineTools
```

### 修改 ESP32 套件強制使用 Python 官方的 Python 3

由於 `python3` 的指令是放在 `/usr/local/bin/` 下, 因此要修改

`~/Library/Arduino15/packages/esp32/hardware/esp32/2.0.2/platform.txt`

檔案, 將其中出現 `python` 的地方修改為 `/usr/local/bin/python3`, 像是這樣：

```
name=ESP32 Arduino
version=
...

tools.esptool_py.network_cmd=/usr/local/bin/python3 "{runtime.platform.path}/tools/espota.py" -r
tools.esptool_py.network_cmd.windows="{runtime.platform.path}/tools/espota.exe" -r

tools.gen_esp32part.cmd=/usr/local/bin/python3 "{runtime.platform.path}/tools/gen_esp32part.py"
...
```

存檔後重新執行 Arduino 就可以正常編譯了。