CPythonをWASMにコンパイルしてみた
2022年10月リリース予定のCPython 3.11では、WASM対応が進行中です。
- Compile Python to WebAssembly (WASM) — Unofficial Python Development (Victor's notes) documentation
- Issue 40280: Consider supporting emscripten/webassembly as a build target - Python tracker
この機能について最低限の動作確認をします。
CPythonのWASM対応
PythonのWASM対応というと、色々な解釈が可能です。
本記事が扱うのは、CPythonインタープリターをEmscripten を用いてWASMにコンパイルすることを意味します。
HTML内でPythonを動かす PyScript のベースになっている Pyodide も同じアプローチです。
PythonプログラムをWASMにコンパイルしたり、PythonプログラムをJavaScriptにトランスパイルするわけではないことにご注意ください。
やってみた
EC2のUbuntu 22.04(x86_64)上で動作させます。
必要なパッケージのインストール
後続処理のために、必要なパッケージをインストールします。
$ sudo apt update
$ sudo apt install -y build-essential zlib1g-dev
Emscripten のインストール
Emscripten は C/C++ プログラムを WebAssembly にコンパイルします。
https://emscripten.org/docs/getting_started/downloads.html を参考に Emscripten をインストールします。
$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source /home/ubuntu/emsdk/emsdk_env.sh
CPythonのコンパイル(Node.JS向け)
次に CPython をコンパイルします。
GitHub レポジトリ ethanhs/python-wasm にビルド用のスクリプトが用意されているので、利用します。
$ git clone https://github.com/ethanhs/python-wasm.git
$ cd python-wasm
$ ./fetch-python.sh # CPython のソースコードを取得
$ ./build-python-build.sh # CPython のビルド
$ ./build-python-emscripten-node.sh # WASM ターゲットの CPython のビルド
Emscriptenのコンパイル時にはCPythonが必要なため、build-python-build.sh
でビルドしています。
EmscriptenのConfigure時に、CPython のパス(--with-build-python
)やビルドターゲット(--with-emscripten-targe
)を指定します。
emconfigure ../../configure -C \
--host=wasm32-unknown-emscripten \
--build=$(../../config.guess) \
--with-emscripten-target=node \
--enable-wasm-dynamic-linking=no \
--with-build-python=$(pwd)/../build/python
REPL を起動してみましょう。
$ node cpython/builddir/emscripten-node/python.js
Python 3.12.0a0 (heads/main-dirty:f62ad4f2c4, May 16 2022, 09:36:30) [Clang 15.0.0 (https://github.com/llvm/llvm-project 8bc29d14273b05b05d5a56e34c07 on emscripten
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'/home/ubuntu/python-wasm/cpython/builddir/emscripten-node/python.js'
>>> sys.platform
'emscripten'
>>> import os
>>> os.uname()
posix.uname_result(sysname='Emscripten', nodename='emscripten', release='1.0', version='#1', machine='wasm32')
CPythonのコンパイル(ブラウザ向け)
同様にして、ブラウザ向けにコンパイルし、REPL のWebアプリを起動します。
$ ./build-python-emscripten-browser.sh # WASM ターゲットの CPython のビルド
# Webアプリの起動
$ ./run-python-browser.sh
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
8000ポートをlocalhost:8000にポートフォワードします。
$ ssh -L 8000:localhost:8000 ubuntu@ec2-xxx-xxx-xxx-xxx.eu-central-1.compute.amazonaws.com
ブラウザで http://localhost:8000 にアクセスしましょう。
ブラウザ上で CPython の REPL が動いていますね。
CPython の main ブランチではなく 3.11 を 利用
GitHub レポジトリ ethanhs/python-wasm を利用すると、fetch-python.sh
の中で CPython を git clone し、デフォルトの main ブランチ(3.12系)を利用しています。
WASM 対応は 3.11 に取り込まれているので、3.11 系ブランチに切り替えたり、 3.11 のソースコードをダウンロードしても、同様に動きます。
$ ./run-python-node.sh
Python 3.11.0b1 (tags/v3.11.0b1-dirty:8d32a5c, May 16 2022, 09:06:19) [Clang 15.0.0 (https://github.com/llvm/llvm-project 8bc29d14273b05b05d5a56e34c07 on emscripten
Type "help", "copyright", "credits" or "license" for more information.
>>>
最後に
CPython WASM 対応の中心人物の一人である Christian Heimes が、2022年4月の PyCon DEでこの取組について発表しています。
Python 3.11 in the Web Browser - A Journey | PyConDE & PyData Berlin 2022
技術的な詳細な応用については、発表をご確認ください。
Discussion