diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 662121654e4f7..7895db4773d45 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -282,3 +282,17 @@ jobs: - name: Print failures if: failure() run: tests/run-tests.py --print-failures + + wasi: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: source tools/ci.sh && ci_unix_wasi_setup + - name: Build + run: source tools/ci.sh && ci_unix_wasi_build + - name: Run main test suite + run: source tools/ci.sh && ci_unix_wasi_run_tests + - name: Print failures + if: failure() + run: tests/run-tests.py --print-failures diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 3c54d156c31ba..f5edd8d990ff0 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -31,7 +31,11 @@ QSTR_DEFS += qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h # OS name, for simple autoconfig +ifeq ($(VARIANT),wasi) +UNAME_S := wasi +else UNAME_S := $(shell uname -s) +endif # include py core make definitions include $(TOP)/py/py.mk @@ -107,7 +111,7 @@ CC = clang endif # Use clang syntax for map file LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip -else +else ifeq ($(UNAME_S),Linux) # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif @@ -303,6 +307,21 @@ $(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure PREFIX = /usr/local BINDIR = $(DESTDIR)$(PREFIX)/bin +ifeq ($(VARIANT),wasi) +# LLVM still uses the older version of EH proposal. ("phase 3") +# Convert to the latest version of EH proposal with exnref. +$(BUILD)/$(PROG).spilled.exnref: $(BUILD)/$(PROG).spilled + $(WASM_OPT) --translate-to-exnref --enable-exception-handling \ + -o $(BUILD)/$(PROG).spilled.exnref $(BUILD)/$(PROG).spilled + +# Unlike emscripten, WASI doesn't provide a way to scan GC roots +# like WASM locals. Hopefully --spill-pointers can workaround it. +$(BUILD)/$(PROG).spilled: $(BUILD)/$(PROG) + $(WASM_OPT) --spill-pointers -o $(BUILD)/$(PROG).spilled $(BUILD)/$(PROG) + +all: $(BUILD)/$(PROG).spilled.exnref +endif + install: $(BUILD)/$(PROG) install -d $(BINDIR) install $(BUILD)/$(PROG) $(BINDIR)/$(PROG) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 21ce75a351e98..44b3f74c8c5ee 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -155,7 +155,9 @@ typedef long mp_off_t; #define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0) // Enable sys.executable. +#ifndef MICROPY_PY_SYS_EXECUTABLE #define MICROPY_PY_SYS_EXECUTABLE (1) +#endif #define MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 5f5abc2e056f6..7af646888f505 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -43,7 +43,13 @@ #endif #endif -#ifndef _WIN32 +#if defined(_WIN32) || defined(__wasi__) +#define HAS_SIGNAL 0 +#else +#define HAS_SIGNAL 1 +#endif + +#if HAS_SIGNAL #include static void sighandler(int signum) { @@ -75,7 +81,7 @@ static void sighandler(int signum) { void mp_hal_set_interrupt_char(char c) { // configure terminal settings to (not) let ctrl-C through if (c == CHAR_CTRL_C) { - #ifndef _WIN32 + #if HAS_SIGNAL // enable signal handler struct sigaction sa; sa.sa_flags = 0; @@ -84,7 +90,7 @@ void mp_hal_set_interrupt_char(char c) { sigaction(SIGINT, &sa, NULL); #endif } else { - #ifndef _WIN32 + #if HAS_SIGNAL // disable signal handler struct sigaction sa; sa.sa_flags = 0; diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h index 9eeed8797366c..24f9f4d4a59b2 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -95,7 +95,9 @@ #define MICROPY_PY_OS_INCLUDEFILE "ports/unix/modos.c" #define MICROPY_PY_OS_ERRNO (1) #define MICROPY_PY_OS_GETENV_PUTENV_UNSETENV (1) +#ifndef MICROPY_PY_OS_SYSTEM #define MICROPY_PY_OS_SYSTEM (1) +#endif #define MICROPY_PY_OS_URANDOM (1) // Enable the unix-specific "time" module. @@ -111,11 +113,15 @@ #endif // The "select" module is enabled by default, but disable select.select(). +#ifndef MICROPY_PY_SELECT_POSIX_OPTIMISATIONS #define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (1) +#endif #define MICROPY_PY_SELECT_SELECT (0) // Enable the "websocket" module. +#ifndef MICROPY_PY_WEBSOCKET #define MICROPY_PY_WEBSOCKET (1) +#endif // Enable the "machine" module, mostly for machine.mem*. #define MICROPY_PY_MACHINE (1) diff --git a/ports/unix/variants/wasi/mpconfigvariant.h b/ports/unix/variants/wasi/mpconfigvariant.h new file mode 100644 index 0000000000000..390926d5a27e9 --- /dev/null +++ b/ports/unix/variants/wasi/mpconfigvariant.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Set base feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// WASI has different values for POLL constants. +#define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (0) + +// WASI doesn't have executable or process. +#define MICROPY_PY_OS_SYSTEM (0) +#define MICROPY_PY_SYS_EXECUTABLE (0) + +// Network support is limited in WASI. +// WebSocket isn't too useful without network. +#define MICROPY_PY_WEBSOCKET (0) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/wasi/mpconfigvariant.mk b/ports/unix/variants/wasi/mpconfigvariant.mk new file mode 100644 index 0000000000000..b4634ddb41707 --- /dev/null +++ b/ports/unix/variants/wasi/mpconfigvariant.mk @@ -0,0 +1,47 @@ +# prerequisites +# +# WASI_SDK: wasi-sdk 25.0 or later +# WASM_OPT: binaryen wasm-opt version_117 or later + +# Note: +# we specify the target "--target=wasm32-wasi" explicitly below for the case +# where $CLANG is built with a configuration different from wasi-sdk. +# ditto for "-B $(WASI_SDK)/bin/". + +WASI_SDK = /opt/wasi-sdk-25.0 +WASI_SYSROOT = $(WASI_SDK)/share/wasi-sysroot +WASM_OPT = wasm-opt +RESOURCE_DIR = $(shell $(WASI_SDK)/bin/clang --print-resource-dir) +CLANG = $(WASI_SDK)/bin/clang + +CC = $(CLANG) --sysroot $(WASI_SYSROOT) -resource-dir $(RESOURCE_DIR) +STRIP = $(WASI_SDK)/bin/strip +SIZE = $(WASI_SDK)/bin/size + +CFLAGS += --target=wasm32-wasi -D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -mllvm -wasm-enable-sjlj +LDFLAGS += --target=wasm32-wasi -lwasi-emulated-process-clocks -lwasi-emulated-signal -lwasi-emulated-mman -lsetjmp -B $(WASI_SDK)/bin/ + +# WASI doesn't have FFI +MICROPY_PY_FFI = 0 + +# When threading is enabled, micropython GC uses signals, which is +# not available on WASI. +MICROPY_PY_THREAD = 0 + +# Disable for now because network support is limited in WASI. +MICROPY_PY_SOCKET = 0 +MICROPY_PY_SSL = 0 + +# ../../lib/berkeley-db-1.xx/PORT/include/db.h:40:10: +# fatal error: 'sys/cdefs.h' file not found +MICROPY_PY_BTREE = 0 + +# WASI doesn't have termios +MICROPY_PY_TERMIOS = 0 +MICROPY_USE_READLINE = 0 + +# The following things might just work as they are. +# Disabled for now because I'm not interested in them. +MICROPY_VFS_FAT = 0 +MICROPY_VFS_LFS1 = 0 +MICROPY_VFS_LFS2 = 0 diff --git a/tests/run-tests.py b/tests/run-tests.py index 628fde9d30a4c..68edf43b5f27d 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -447,8 +447,9 @@ def send_get(what): cmdlist = [os.path.abspath(MICROPYTHON), "-X", "emit=" + args.emit] if args.heapsize is not None: cmdlist.extend(["-X", "heapsize=" + args.heapsize]) - if sys.platform == "darwin": - cmdlist.extend(["-X", "realtime"]) + if os.getenv("MICROPY_MICROPYTHON_WASM") is None: + if sys.platform == "darwin": + cmdlist.extend(["-X", "realtime"]) cwd = os.path.dirname(test_file) diff --git a/tools/ci.sh b/tools/ci.sh index b0e59509add83..2c19bf4efe4cf 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -852,6 +852,36 @@ function ci_unix_qemu_riscv64_run_tests { (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py) } +function ci_unix_wasi_setup { + wget https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-x86_64-linux.tar.gz + zcat binaryen-version_123-x86_64-linux.tar.gz | tar x + wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + zcat wasi-sdk-25.0-x86_64-linux.tar.gz | tar x + wget https://github.com/yamt/toywasm/releases/download/v68.0.0/toywasm-v68.0.0-full-ubuntu-22.04-amd64.tgz + mkdir toywasm + zcat toywasm-v68.0.0-full-ubuntu-22.04-amd64.tgz | tar -C toywasm -x +} + +function ci_unix_wasi_build { + make ${MAKEOPTS} -C ports/unix VARIANT=wasi \ + WASI_SDK=$(pwd -P)/wasi-sdk-25.0-x86_64-linux \ + WASM_OPT=$(pwd -P)/binaryen-version_123/bin/wasm-opt \ + submodules + make ${MAKEOPTS} -C ports/unix VARIANT=wasi \ + WASI_SDK=$(pwd -P)/wasi-sdk-25.0-x86_64-linux \ + WASM_OPT=$(pwd -P)/binaryen-version_123/bin/wasm-opt +} + +function ci_unix_wasi_run_tests { + # Note: for simplicity, use absolute path where possible + # because wasi doesn't have the concept of "current directory" natively. + (cd tests && \ + MICROPY_MICROPYTHON=$(pwd -P)/../tools/run-with-toywasm.sh \ + TOYWASM=$(pwd -P)/../toywasm/bin/toywasm \ + MICROPY_MICROPYTHON_WASM=$(pwd -P)/../ports/unix/build-wasi/micropython.spilled.exnref \ + ./run-tests.py -d $(pwd -P)/basics) +} + ######################################################################################## # ports/windows diff --git a/tools/run-with-toywasm.sh b/tools/run-with-toywasm.sh new file mode 100755 index 0000000000000..e1da14e1c4fac --- /dev/null +++ b/tools/run-with-toywasm.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +if [ ! -e "${MICROPY_MICROPYTHON_WASM}" ]; then + echo "MICROPY_MICROPYTHON_WASM is not set properly" >&2 + exit 1 +fi + +exec ${TOYWASM:-toywasm} --wasi --wasi-dir=/ \ +${MICROPY_MICROPYTHON_WASM} \ +-- "$@" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy