🧩

CPythonをWASMにコンパイルしてみた

2022/05/16に公開

2022年10月リリース予定のCPython 3.11では、WASM対応が進行中です。

この機能について最低限の動作確認をします。

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

技術的な詳細な応用については、発表をご確認ください。

https://www.youtube.com/watch?v=oa2LllRZUlU

https://speakerdeck.com/tiran/python-3-dot-11-in-the-web-browser-a-journey-pycon-de-2022-keynote

参考

Discussion