概要
Arduino IDEでのESP32をビルドする時間がどうしてもかかってしまうので、WSL上でArduino IDEを動かしてみました。半分まではいきませんでしたが30%以上は高速化することができました。
ただしパソコンの管理者権限が必要だったり、ファイアーウォールの設定変更ができないとなかなか厳しいです。
ビルドが遅い原因
Windowsの場合にはセキュリティ強化のため、すべての操作に対してウイルスチェックなどが動き、細かいファイルを大量に操作するビルドが非常に遅くなります。とくにESP32は環境的に大きいので非常に時間がかかってしまいます。
Microsoft Defenderなどのウイルス対策ソフトの除外フォルダの設定などでArduino IDEの環境を追加することである程度対策をすることが可能です。しかし設定を変更できない環境や、どこのフォルダを除外に追加すればよいのかわからない場合には対応できません。
似たような設定としてDev Driveがあります。開発用のフラグを有効にした仮想ハードディスクを作成して、そのドライブの中身はウイルスチェックをゆるくする仕組みになります。
ディレクトリにもマウント可能ですのでArduino IDEの環境をまるごとDev Driveに持っていくことも可能です。ただし、Microsoft Defenderなど特定のウイルス対策ソフト以外だとDev Driveの開発用のフラグを参照していないようで、効果がないソフトもあったりします。
そこで、デフォルトでウイルス対策ソフトの管理外になるWSL上にArduino IDE環境を作って動かしてみました。
構築手順
WSLにてUbuntu 24.04の環境を立ち上げます。また、Windows上のWSL環境は秘伝のタレ的になりやすいので環境をすぐに再現できるようなスクリプトを準備したいと思います。
環境破壊
wsl --list
上記で設定済みのWSLを確認します。
wsl --unregister Ubuntu
Ubuntuがいましたので上記で削除します。もちろん、必要なファイルとかがあったら保存しておきます。
wsl --list
環境がなくなったのを確認します。
Ubuntu 24.04のインストール
wsl --install -d Ubuntu-24.04
上記でUbuntuをいれます。バージョンは指定したほうが明示的でよいと思います。
Windows上にセットアップ用のファイルを準備する
- /mnt/c/Users/%username%/Dropbox/wsl/install.sh
私は上記のような場所にセットアップ用のフォルダとファイルを準備しました。Dropbox上にしたので全部のマシンで共有しています。dockerフォルダとかを作って、その中に保存しないといけないファイルを置いておきます。
# wsl --unregister Ubuntu-24.04
# wsl --install -d Ubuntu-24.04
# bash /mnt/c/Users/tanaka/Dropbox/wsl/windows10.sh
# bash /mnt/c/Users/tanaka/Dropbox/wsl/install.sh
ln -s /mnt/c/Users/tanaka/Dropbox/wsl/ ~/windows
echo
echo "apt update"
sudo apt update
echo
echo "apt upgrade"
sudo apt -y upgrade
echo
echo "apt install common tools"
sudo apt -y install unzip bind9-dnsutils
とりあえずは上記のようなファイルを置いて置きました。もう少し書いてありますが自分でデフォルトで使うツールとかは最初に一括にいれます。
Windows10の場合にはDNSの設定を変更する
Windows11で最新のWSLを利用している場合にはDNSが標準で利用できるが、それ以外の環境の場合にはDNS Tunnelingが利用できないので追加のスクリプトを準備して実行する。
ping www.google.com
WSL上で上記のコマンドを実行して、成功しない場合にはDNSが利用できない環境になります。
sudo sh -c 'echo "[network]">>/etc/wsl.conf'
sudo sh -c 'echo "generateResolvConf = false">>/etc/wsl.conf'
sudo rm /etc/resolv.conf
sudo sh -c "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"
上記をwsl/windows10.shに保存して実行することでDNS関係を上書きしています。ちなみに後ろの方にでてくるHyper-Vをいれることで無設定でこのDNS問題も解決します。
初期セットアップスクリプトを実行
bash /mnt/c/Users/tanaka/Dropbox/wsl/install.sh
私の場合には上記のようなファイルを実行します。これでaptの更新とunzipとnslookupとかを使えるようにします。
Arduino IDEのダウンロード
cd ~
wget https://downloads.arduino.cc/arduino-ide/arduino-ide_2.3.2_Linux_64bit.zip
上記でArduino IDEをダウンロードしてきます。
バージョンは最新のものを上記のページで確認してください。
展開
unzip arduino-ide_2.3.2_Linux_64bit.zip
rm arduino-ide_2.3.2_Linux_64bit.zip
ファイルを展開して、不要になったzipファイルを消しています。ここでunzipコマンドを利用していますので入っていない環境の場合には「sudo apt install unzip」を実行する必要があります。
実行する
cd arduino-ide_2.3.2_Linux_64bit
./arduino-ide
実行してみます。おそらくエラーがでたと思います。このエラーを消していくことで実行できるようになります。
ちなみにUbuntu 24.04がでた直後の場合には「./arduino-ide」では起動せずに「./arduino-ide –no-sandbox」にする必要がありました。現在確認したところ–no-sandboxは必要なくなったみたいです。
必要なパッケージをインストールする
sudo apt install libnss3 libasound2t64 libsecret-1-0 fonts-noto-cjk-extra
私の環境では上記のパッケージが必要でした。最後は日本語フォントですので英語モードで利用する場合には必要ありません。
(必須ではない)日本語変換できるようにする
sudo apt install fcitx5-mozc
必須ではありませんが、上記で日本語変換をするMozcを追加します。
fcitx5-configtool
その後上記で設定画面を呼び出します。
最初に起動するボタンを押してから右上のフィルタリングでjaと入力してからEnglishを消して、上記の状態にします。これでCtrl+スペースで日本語入力ができるようになりました。ちなみに自動起動していませんのでご注意ください。
個人的にはWSL環境のArduino IDE上での日本語入力はあきらめて、「code .」などでvscodeを呼び出して、Arduino IDEはビルドだけに利用する方がおすすめです。
Arduino IDEの起動
./arduino-ide
起動してみます。英語モードで起動したら成功です。
設定から日本語に変更して、ボードマネージャのURLを追加します。
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
とりあえずESP32のボードマネージャを追加してみました。この時点でまだUSBデバイスは認識していないはずです。
WindowsのUSB共有usbipd-winを入れる
上記からWindows上のUSBデバイスをWSLで使えるようにするツールを入れます。
winget install usbipd
上記のコマンドかGitHubから最新のインストーラーを実行してセットアップします。このツールはUSBをTCPを利用した通信に変換してくれることでUSBデバイスがWSLで利用可能になります。ただし、通信が発生するのでファイアウォールの設定が必要になります。
最初にデバイスを共有可能設定にするために管理者権限が必要になります。コマンドプロンプトかPowerShellを管理者権限で実行させます。
usbipd list
上記でデバイスの接続先を確認します。一番左にあるBUSIDを利用して接続を行いますのでメモしておきます。
usbipd bind -b 1-3
最初に共有できるようにbindコマンドで共有設定にします。1-3がBUSIDで接続しているUSBポートなどによりことなると思います。
usbipd attach -b 1-3 -w
bindしたデバイスをattachで実際にWSLに割り当てます。このときにTCPの3240番ポートがみたいなエラーがでたらファイアーウォールにブロックされています。Microsoft Defenderなど利用しているファイアーウォールの設定を変更してブロックを解除してあげてください。
エラー発生時の回避方法
そしていろいろ検証した結果、ファイアーウォールの設定ができない環境の場合には「Hyper-V」を有効化することで内部の通信がHyper-Vファイアーウォール経由になり内部通信が許可されます。ただし、新規にWSL環境を作り直す必要があるので「wsl –unregister Ubuntu-24.04」で環境を破壊して、「wsl –install Ubuntu-24.04」で作り直すことが必要です。
上記のようにHyper-Vマネージャーから仮想スイッチをみてみると「WSL (Hyper-V firewall)」が追加されています。内部的な通信はすべてこのファイアーウォールになり、Windows側のファイアーウォールをバイパスできるようでした。
そして、WSLのすべての設定を最初からやりなおします。作ってよかった初期セットアップスクリプト!
GUIツールの導入
コマンドラインで設定すればいいのですがやっぱり面倒なのでGUIツールを入れてみました。このツールかコマンドラインでESP32ボードのシリアルポートをWSLでバインドできるように設定します。
上記の様な画面になり、デバイスを追加すると色が変わった行がでますので、その行をバインドしてからアタッチすることで真ん中の項目に移動します。移動に失敗するときにはファイアウォールなどによりWindowsとWSL間の通信がブロックされています。そしてWSL上のArduino IDEにシリアルポートが追加されたら成功です。
WindowsネイティブとWSLでビルド時間測定
ESP32/MacAddress/GetMacAddress
一番単純と思われるスケッチ例で試してみました。Windowsネイティブ環境と同じマシンのWSL上でArduino IDEを利用して初回ビルドから転送完了までを試してみました。
Windowsネイティブ | WSL |
---|---|
37秒 | 26秒 |
70%に短縮 |
半分まではいきませんでしたが、Windowsが多少カクついている場所もWSL上のArduino IDEはすすんでいる感じでした。ビルドよりもその前のライブラリ検索などが重い可能性もありますね。今回は詳しい分析はしていません。
M5Unified/Basic/HowToUse
続いて、非常にビルド時間がかかる大型スケッチ例としてM5Unifiedの初回ビルドから転送までを試してみました。
Windowsネイティブ | WSL |
---|---|
3分36秒 | 1分53秒 |
52%に短縮 |
こちらも半分にはならなかったですが、あきらかに高速化しています。
CH32V
ちょっと環境をかえて、自作のCH32V環境でも試してみました。こちらはタイムを計測していませんでしたがWSL環境で転送が非常に遅いという問題が発覚しました。VirtualBoxなどの仮想環境でUSBを共有した場合にも同じ問題が発生するのですがUSBシリアルなど一方的に大量データを送信するタイプは問題ないのですが、SWDやJTAGなどの通信をする場合にはスループットがでません。
そのためCH32Vの小さなファームウエアを転送するだけでも仮想環境だとハングアップしたのかなと思うぐらい時間がかかります。Linux環境でのビルドテストとしては利用可能ですが、頻繁に転送を行うのであればWindowsネイティブ環境で転送したほうがストレスはないかもしれません。
macbook(M2)と比べる
M2を搭載したmacbook airでも計測してみて、圧倒的な実力差をみたかったのですが、、、
ESP32/MacAddress/GetMacAddress
Windowsネイティブ | WSL | M2 macbook |
---|---|---|
37秒 | 26秒 | 40秒 |
70%に短縮 | 108%に悪化 |
あれ、、、遅くなっている。利用したM2 macbook airはウイルス対策ソフトが入っているものだったのでその可能性がありますが最初に一定時間流れていない時間があったようで、そこでひっかかったみたいです。
M5Unified/Basic/HowToUse
Windowsネイティブ | WSL | M2 macbook |
---|---|---|
3分36秒 | 1分53秒 | 1分30秒 |
52%に短縮 | 42%に短縮 |
大きなプロジェクトだと最初のロスタイムはあるようですが、ビルド自体は早かったです。Windowsネイティブ環境の半分以下になっているのでかなり違いますね。
まとめ
usbipdが利用できずにかなり苦しんでいたのですが、まさかのHyper-Vを入れることで回避できるとは思っていませんでした。たまたま最初に検証したマシンでHyper-Vの検証をしていて、その後にクリーンなWindows11で手順確認したところファイアーウォールにハマって苦しんでいました。
Wiresharkとかで流れているパケットを確認して、そういえばとインターフェース名をチェックしてやっと差分を見つけることができました。
あとWSL上のLinux環境は通常のLinux環境とほぼ同じ動きをするので、プラットフォーム別の確認などもで利用できると思います。
コメント