diff --git a/ports/unix/Makefile b/ports/unix/Makefile index d5bd6d4098..9a9df82629 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -103,7 +103,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 diff --git a/ports/unix/build-wasi.sh b/ports/unix/build-wasi.sh new file mode 100755 index 0000000000..9a99fca3c9 --- /dev/null +++ b/ports/unix/build-wasi.sh @@ -0,0 +1,54 @@ +#! /bin/sh + +# prerequisites +# +# https://github.com/WebAssembly/wasi-libc/pull/483 (wasi-sdk 22.0?) +# https://github.com/WebAssembly/wasi-libc/pull/473 (wasi-sdk 22.0?) +# https://github.com/WebAssembly/binaryen/pull/6294 (version_117) +# https://github.com/WebAssembly/binaryen/pull/6259 (version_117) +# https://github.com/llvm/llvm-project/pull/84137 (LLVM 19?) +# +# WASI_SDK: wasi-sdk 21.0 +# WASM_OPT: binaryen wasm-opt built with the above patches +# WASI_SYSROOT: wasi-libc built with the above patches +# CLANG: clang built with the above patches + +WASI_SDK=${WASI_SDK:-/opt/wasi-sdk-21.0} +WASI_SYSROOT=${WASI_SYSROOT:-${HOME}/git/wasi-libc/sysroot} +BINARYEN_BIN=${BINARYEN_BIN:-${HOME}/git/wasm/binaryen/b/bin} +WASM_OPT=${WASM_OPT:-${BINARYEN_BIN}/wasm-opt} +RESOURCE_DIR=$(${WASI_SDK}/bin/clang --print-resource-dir) +LLVM_BUILD_DIR=${LLVM_BUILD_DIR:-/Volumes/PortableSSD/llvm/build} +CLANG=${CLANG:-${LLVM_BUILD_DIR}/bin/clang} +CC="${CLANG} --sysroot ${WASI_SYSROOT} -resource-dir ${RESOURCE_DIR}" + +CFLAGS="-D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -mllvm -wasm-enable-sjlj" \ +LDFLAGS="-lwasi-emulated-process-clocks -lwasi-emulated-signal -lwasi-emulated-mman -lsetjmp" \ +make \ +CC="${CC}" \ +LD="${WASI_SDK}/bin/wasm-ld" \ +STRIP="${WASI_SDK}/bin/strip" \ +SIZE="${WASI_SDK}/bin/size" \ +UNAME_S=wasi \ +VARIANT=wasi \ +"$@" + +PROG=build-wasi/micropython + +# We doesn't have a way to scan GC roots like WASM locals. +# Hopefully --spill-pointers can workaround it. +${WASM_OPT} \ +--spill-pointers \ +-o ${PROG}.spilled ${PROG} + +# LLVM still uses the older version of EH proposal. +# Convert to the latest version of EH proposal. +${WASM_OPT} \ +--translate-to-new-eh --enable-exception-handling \ +-o ${PROG}.spilled.neweh ${PROG}.spilled + +# now you can run it with EH-enabled runtimes. +# eg. (using the latest EH) +# toywasm --wasi build-wasi/micropython.spilled.neweh +# eg. (using the old EH) +# iwasm build-wasi/micropython.spilled diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 1086baea06..3265ca84e8 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 5f5abc2e05..3ea3107d54 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 != 0 #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 != 0 // 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 != 0 // 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 2e34055bf7..5f709d3b51 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -96,7 +96,9 @@ #define MICROPY_PY_OS_ERRNO (1) #define MICROPY_PY_OS_GETENV_PUTENV_UNSETENV (1) #define MICROPY_PY_OS_SEP (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. @@ -112,7 +114,9 @@ #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. diff --git a/ports/unix/variants/wasi/manifest.py b/ports/unix/variants/wasi/manifest.py new file mode 100644 index 0000000000..d27bf3c47f --- /dev/null +++ b/ports/unix/variants/wasi/manifest.py @@ -0,0 +1,3 @@ +include("$(PORT_DIR)/variants/manifest.py") + +include("$(MPY_DIR)/extmod/asyncio") diff --git a/ports/unix/variants/wasi/mpconfigvariant.h b/ports/unix/variants/wasi/mpconfigvariant.h new file mode 100644 index 0000000000..95d0a47fe8 --- /dev/null +++ b/ports/unix/variants/wasi/mpconfigvariant.h @@ -0,0 +1,38 @@ +/* + * 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) + +// 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 0000000000..c78d9cc15b --- /dev/null +++ b/ports/unix/variants/wasi/mpconfigvariant.mk @@ -0,0 +1,28 @@ +# Build for WASI + +FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py + +# 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