-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
155 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,26 @@ | ||
# WasmPy-Build | ||
|
||
This tool can compile CPython C extension files, such as the ones created by Cython, to WebAssembly so that the extensions are platform independent. | ||
|
||
The created `.wasm` files can be imported by [WasmPy](https://github.com/olivi-r/wasmpy) in a simmilar manner to native C extensions. | ||
|
||
This project contains modified CPython header files as well as a build script to ease the creation of `.wasm` extension files. | ||
|
||
Currently this project only supports CPython 3.8, 3.9 and 3.10 but I'm hoping to add support for older versions. | ||
|
||
# Installation | ||
|
||
To install WasmPy-Build you will first need to install the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html#installation-instructions). | ||
|
||
### Install WasmPy-Build from pip | ||
|
||
```bash | ||
$ pip install wasmpy-build | ||
``` | ||
|
||
### ... or build from source | ||
|
||
```bash | ||
$ git clone --recurse-submodules https://github.com/olivi-r/wasmpy-build | ||
$ cd wasmpy-build | ||
$ python -m pip install -r requirements.txt | ||
$ python patch_headers.py | ||
$ python setup.py install | ||
``` | ||
# wasmpy-build | ||
|
||
This tool can compile CPython C extension files, such as the ones created by Cython, to WebAssembly so that the extensions are platform independent. | ||
|
||
This project contains modified CPython header files as well as a build script to ease the creation of `.wasm` extension files. | ||
|
||
Currently this project only supports CPython 3.8, 3.9, 3.10 and 3.11 but I'm hoping to add support for older and future versions. | ||
|
||
The project will automatically download [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) on first use. | ||
|
||
# Installation | ||
### Install from pip | ||
|
||
```bash | ||
pip install wasmpy-build | ||
``` | ||
|
||
### or build from source | ||
|
||
```bash | ||
git clone --recurse-submodules https://github.com/olivi-r/wasmpy-build | ||
cd wasmpy-build | ||
python -m pip install -r requirements.txt | ||
python patch_headers.py | ||
python setup.py install | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
patch | ||
appdirs | ||
patch | ||
requests | ||
tqdm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,40 @@ | ||
import os, setuptools | ||
|
||
with open("README.md") as fp: | ||
long_description = fp.read() | ||
|
||
def recurse_files(directory): | ||
paths = [] | ||
for path, dirs, files in os.walk(directory): | ||
for file in files: | ||
paths.append(os.path.join("..", path, file)) | ||
|
||
return paths | ||
|
||
setuptools.setup( | ||
name="wasmpy-build", | ||
version="0.2.1", | ||
author="Olivia Ryan", | ||
author_email="[email protected]", | ||
description="Emscripten compatible build script for CPython C extensions", | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/olivi-r/wasmpy-build", | ||
packages=["wasmpy_build"], | ||
package_data={ | ||
"wasmpy_build": recurse_files("wasmpy_build/include") | ||
}, | ||
entry_points={ | ||
"console_scripts": [ | ||
"wasmpy-build=wasmpy_build:build" | ||
] | ||
}, | ||
classifiers=[ | ||
"Programming Language :: C", | ||
"Programming Language :: Cython", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: Implementation :: CPython", | ||
"License :: OSI Approved :: MIT License", | ||
], | ||
license="MIT", | ||
python_requires=">=3.8" | ||
) | ||
import os, setuptools | ||
|
||
|
||
with open("README.md") as fp: | ||
long_description = fp.read() | ||
|
||
|
||
def recurse_files(directory): | ||
paths = [] | ||
for path, _, files in os.walk(directory): | ||
for file in files: | ||
paths.append(os.path.join("..", path, file)) | ||
|
||
return paths | ||
|
||
|
||
setuptools.setup( | ||
name="wasmpy-build", | ||
version="0.3.0", | ||
author="Olivia Ryan", | ||
author_email="[email protected]", | ||
description="WebAssembly build tool for CPython C extensions", | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/olivi-r/wasmpy-build", | ||
packages=["wasmpy_build"], | ||
package_data={"wasmpy_build": recurse_files("wasmpy_build/include")}, | ||
entry_points={"console_scripts": ["wasmpy-build=wasmpy_build:build"]}, | ||
classifiers=[ | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: Implementation :: CPython", | ||
"License :: OSI Approved :: MIT License", | ||
], | ||
license="MIT", | ||
python_requires=">=3.8", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,79 @@ | ||
import os, platform, subprocess, sys | ||
|
||
|
||
def build(): | ||
command = sys.argv[1:] | ||
|
||
# find cpython include files | ||
include_dir = os.path.join(os.path.dirname(__file__), "include", "cp") | ||
version = "".join(str(i) for i in sys.version_info[:2]) | ||
include_dir += version | ||
|
||
if "-o" not in command: | ||
command += ["-o", f"a.out.cp{version}.wasm"] | ||
|
||
emcc = "emcc.bat" if platform.system() == "Windows" else "emcc" | ||
args = ( | ||
[ | ||
emcc, | ||
"-Wno-visibility", | ||
"-Wno-experimental", | ||
f"-I{include_dir}", | ||
"-sSIDE_MODULE", | ||
"-sSTANDALONE_WASM", | ||
"-DSIZEOF_WCHAR_T", | ||
"-DHAVE_PTHREAD_STUBS", | ||
"-pthread", | ||
] | ||
+ [] | ||
if "-o" in command | ||
else ["-o", f"a.out.cp{version}.wasm"] | ||
) | ||
try: | ||
subprocess.call(args + command) | ||
|
||
except FileNotFoundError: | ||
print( | ||
"emsdk not found\nYou can install it from https://github.com/emscripten-core/emsdk\nIf it is already installed make sure to call the emsdk_env.sh/emsdk_env.bat script or add emsdk to path." | ||
) | ||
import os, platform, shutil, subprocess, sys, tarfile | ||
import appdirs, requests, tqdm | ||
|
||
|
||
sdk_dir = os.path.join(appdirs.user_data_dir("wasmpy-build", "wasmpy")) | ||
|
||
|
||
def download_sdk(): | ||
try: | ||
os.makedirs(sdk_dir) | ||
|
||
except FileExistsError: | ||
pass | ||
|
||
url = ( | ||
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/" | ||
) | ||
if platform.system() == "Windows": | ||
file = "wasi-sdk-20.0.m-mingw.tar.gz" | ||
|
||
elif platform.system() == "Linux": | ||
file = "wasi-sdk-20.0-linux.tar.gz" | ||
|
||
url += file | ||
if not os.path.exists(os.path.join(sdk_dir, file)): | ||
print(f"Downloading {file}") | ||
with requests.get(url, stream=True) as req: | ||
req.raise_for_status() | ||
|
||
with open(os.path.join(sdk_dir, file), "wb+") as fp, tqdm.tqdm( | ||
desc=file, | ||
total=int(req.headers.get("content-length", 0)), | ||
unit="MiB", | ||
unit_scale=True, | ||
unit_divisor=1024, | ||
) as progress: | ||
for chunk in req.iter_content(4096): | ||
progress.update(fp.write(chunk)) | ||
|
||
print(f"Extracting {file}") | ||
with tarfile.open(os.path.join(sdk_dir, file)) as tar: | ||
extracted = tar.getnames()[0] | ||
tar.extractall(sdk_dir) | ||
|
||
shutil.move( | ||
os.path.join(sdk_dir, extracted), | ||
os.path.join(sdk_dir, f"sdk-{platform.system()}"), | ||
) | ||
|
||
print(f"wasi-sdk installed at: {os.path.join(sdk_dir, 'sdk')}") | ||
build() | ||
|
||
|
||
def build(): | ||
command = sys.argv[1:] | ||
|
||
# find cpython include files | ||
include_dir = os.path.join(os.path.dirname(__file__), "include", "cp") | ||
version = "".join(str(i) for i in sys.version_info[:2]) | ||
include_dir += version | ||
|
||
args = [ | ||
f"{sdk_dir}/sdk-{platform.system()}/bin/clang", | ||
"--target=wasm32-unknown-wasi", | ||
f"--sysroot={sdk_dir}/sdk-{platform.system()}/share/wasi-sysroot", | ||
"-nostartfiles", | ||
"-D_POSIX_THREADS", | ||
"-DHAVE_PTHREAD_STUBS", | ||
"-DSIZEOF_WCHAR_T=2", | ||
f"-I{include_dir}", | ||
] + command | ||
|
||
print(" ".join(args)) | ||
try: | ||
subprocess.call(args) | ||
|
||
except FileNotFoundError: | ||
print("wasi-sdk not found") | ||
download_sdk() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
from . import build | ||
|
||
if __name__ == "__main__": | ||
build() | ||
from . import build | ||
|
||
|
||
if __name__ == "__main__": | ||
build() |