Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions ports/unix/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ endif
# If the build directory is not given, make it reflect the variant name.
BUILD ?= build-$(VARIANT)

ifneq ($(MICROPY_FORCE_32BIT),)
$(warning *** The MICROPY_FORCE_32BIT flag is no longer affecting builds, please update your environment ***)
endif

include ../../py/mkenv.mk
-include mpconfigport.mk
include $(VARIANT_DIR)/mpconfigvariant.mk
Expand Down Expand Up @@ -107,11 +111,7 @@ endif
# while cross-compile ports require gcc, so we test here for OSX and
# if necessary override the value of 'CC' set in py/mkenv.mk
ifeq ($(UNAME_S),Darwin)
ifeq ($(MICROPY_FORCE_32BIT),1)
CC = clang -m32
else
CC = clang
endif
# Use clang syntax for map file
LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip
else
Expand Down Expand Up @@ -174,11 +174,7 @@ ifeq ($(MICROPY_STANDALONE),1)
GIT_SUBMODULES += lib/libffi
DEPLIBS += libffi
LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/include)
ifeq ($(MICROPY_FORCE_32BIT),1)
LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib32/libffi.a
else
LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib/libffi.a
endif
LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib/libffi.a
else
# Use system version of libffi.
LIBFFI_CFLAGS := $(shell pkg-config --cflags libffi)
Expand Down Expand Up @@ -239,10 +235,6 @@ ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs
endif

ifeq ($(MICROPY_FORCE_32BIT),1)
RUN_TESTS_MPY_CROSS_FLAGS = --mpy-cross-flags='-march=x86'
endif

ifeq ($(CROSS_COMPILE),arm-linux-gnueabi-)
# Force disable error text compression when compiling for ARM as the compiler
# cannot optimise out the giant strcmp list generated for MP_MATCH_COMPRESSED.
Expand Down
70 changes: 66 additions & 4 deletions ports/unix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ The "unix" port runs in standard Unix-like environments including Linux, BSD,
macOS, and Windows Subsystem for Linux.

The x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well
as ARM and MIPS. Extending the unix port to another architecture requires
writing some assembly code for the exception handling and garbage collection.
Alternatively, a fallback implementation based on setjmp/longjmp can be used.
as ARM, MIPS, and RISC-V. Extending the unix port to another architecture
requires writing some assembly code for the exception handling and garbage
collection. Alternatively, a fallback implementation based on setjmp/longjmp
can be used.

Building
--------
Expand All @@ -18,7 +19,7 @@ To build the unix port locally then you will need:

* git command line executable, unless you downloaded a source .tar.xz file from
https://micropython.org/download/
* gcc (or clang for macOS) toolchain
* an appropriate gcc (or clang for macOS) toolchain for your target
* GNU Make
* Python 3.x

Expand Down Expand Up @@ -181,3 +182,64 @@ Several classes of checks are disabled via compiler flags:
check is intended to make sure locals in a "returned from" stack frame are not
used. However, this mode interferes with various assumptions that
MicroPython's stack checking, NLR, and GC rely on.

### Notes about x86 (i686) support

It used to be possible to create an x86 (32-bits) build on a x64 (64-bits) host
by passing `MICROPY_FORCE_32BIT=1` to `make`. That option was retired: x86
usage has declined quite a bit in the past few years, and MicroPython now
supports at least one more mixed 32/64-bits target architecture for which
enabling `MICROPY_FORCE_32BIT` would make builds fail.

x86 will be treated as a cross-compilation target from now on. This means you
will need to install a suitable compiler (on Ubuntu you can install the
`gcc-i686-linux-gnu` and `g++-i686-linux-gnu` packages, for example) and pass
the toolchain's command prefix to the `CROSS_COMPILE` command line variable.

This change is also extended to native modules, for which you may need to pass
the toolchain's command prefix to the `CROSS` command line variable if your
x86 compiler cannot be invoked with `i686-linux-gnu-gcc`.

Or, as an example:

```bash
$ printf "%s %s %s %s\n" $(lsb_release -d | cut -f 2) $(uname -m)
Ubuntu 24.04.3 LTS x86_64

$ i686-linux-gnu-gcc --version | head -n 1
i686-linux-gnu-gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0

$ CROSS_COMPILE=i686-linux-gnu- make -C ports/unix
make: Entering directory '/ports/unix'
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
...
LINK build-standard/micropython
text data bss dec hex filename
718479 36016 2092 756587 b8b6b build-standard/micropython
make: Leaving directory '/ports/unix'

$ file -b ports/unix/build-standard/micropython | cut -d, -f-2
ELF 32-bit LSB pie executable, Intel 80386

# `i686-linux-gnu-` is the default prefix for x86 native modules now, it has
# been explicitly mentioned here in case you want to see how to set it.

$ make -C examples/natmod/features0 ARCH=x86 CROSS=i686-linux-gnu-
make: Entering directory '/examples/natmod/features0'
GEN build/features0.config.h
CC features0.c
LINK build/features0.o
arch: EM_386
text size: 196
bss size: 0
GOT entries: 4
GEN features0.mpy
make: Leaving directory '/examples/natmod/features0'

$ cd examples/natmod/features0 && ../../../ports/unix/build-standard/micropython
MicroPython v1.28.0-preview.63.g8189e9935a.dirty on 2026-01-09; linux [GCC 13.3.0] version
Type "help()" for more information.
>>> import features0
>>> features0.factorial(10)
3628800
```
4 changes: 2 additions & 2 deletions ports/unix/variants/longlong/mpconfigvariant.mk
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# build interpreter with "bigints" implemented as "longlong"

# otherwise, small int is essentially 64-bit
MICROPY_FORCE_32BIT := 1
# This needs to be built for a 32-bits target, otherwise small ints will
# essentially be 64-bit wide.

MICROPY_PY_FFI := 0

Expand Down
3 changes: 2 additions & 1 deletion ports/unix/variants/nanbox/mpconfigvariant.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# build interpreter with nan-boxing as object model (object repr D)

MICROPY_FORCE_32BIT = 1
# This needs to be built for a 32-bits target, as object representation D is
# only meant to work on 32-bits machines.
7 changes: 7 additions & 0 deletions ports/windows/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ PROG ?= micropython
QSTR_DEFS += ../unix/qstrdefsport.h
QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h

# Enable building 32-bit code on 64-bit hosts.
ifeq ($(MICROPY_FORCE_32BIT),1)
CC += -m32
CXX += -m32
LD += -m32
endif

# include py core make definitions
include $(TOP)/py/py.mk
include $(TOP)/extmod/extmod.mk
Expand Down
4 changes: 2 additions & 2 deletions py/dynruntime.mk
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ CLEAN_EXTRA += $(MOD).mpy .mpy_ld_cache
ifeq ($(ARCH),x86)

# x86
CROSS =
CFLAGS_ARCH += -m32 -fno-stack-protector
CROSS = i686-linux-gnu-
CFLAGS_ARCH += -fno-stack-protector
MICROPY_FLOAT_IMPL ?= double

else ifeq ($(ARCH),x64)
Expand Down
7 changes: 0 additions & 7 deletions py/py.mk
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ QSTR_GLOBAL_REQUIREMENTS += $(HEADER_BUILD)/mpversion.h
# some code is performance bottleneck and compiled with other optimization options
CSUPEROPT = -O3

# Enable building 32-bit code on 64-bit host.
ifeq ($(MICROPY_FORCE_32BIT),1)
CC += -m32
CXX += -m32
LD += -m32
endif

# External modules written in C.
ifneq ($(USER_C_MODULES),)
# pre-define USERMOD variables as expanded so that variables are immediate
Expand Down
28 changes: 16 additions & 12 deletions tools/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -623,9 +623,12 @@ CI_UNIX_OPTS_SANITIZE_UNDEFINED=(
CI_UNIX_OPTS_REPR_B=(
VARIANT=standard
CFLAGS_EXTRA="-DMICROPY_OBJ_REPR=MICROPY_OBJ_REPR_B -DMICROPY_PY_UCTYPES=0 -Dmp_int_t=int32_t -Dmp_uint_t=uint32_t"
MICROPY_FORCE_32BIT=1
RUN_TESTS_MPY_CROSS_FLAGS="--mpy-cross-flags=\"-march=x86 -msmall-int-bits=30\""
)

CI_UNIX_OPTS_X86=(
CROSS_COMPILE=i686-linux-gnu-
RUN_TESTS_MPY_CROSS_FLAGS=${RUN_TESTS_MPY_CROSS_FLAGS:-"--mpy-cross-flags=\"-march=x86\""}
)

function ci_unix_build_helper {
Expand Down Expand Up @@ -766,37 +769,38 @@ function ci_unix_coverage_run_native_mpy_tests {
function ci_unix_32bit_setup {
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install gcc-multilib g++-multilib libffi-dev:i386
sudo apt-get install gcc-i686-linux-gnu g++-i686-linux-gnu patchelf libffi-dev:i386
python -m pip install pyelftools
python -m pip install ar
gcc --version
i686-linux-gnu-gcc --version
python3 --version
}

function ci_unix_coverage_32bit_build {
ci_unix_build_helper VARIANT=coverage MICROPY_FORCE_32BIT=1
ci_unix_build_ffi_lib_helper gcc -m32
ci_unix_build_helper VARIANT=coverage "${CI_UNIX_OPTS_X86[@]}"
ci_unix_build_ffi_lib_helper i686-linux-gnu-gcc
}

function ci_unix_coverage_32bit_run_tests {
ci_unix_run_tests_full_helper coverage MICROPY_FORCE_32BIT=1
ci_unix_run_tests_full_helper coverage "${CI_UNIX_OPTS_X86[@]}"
}

function ci_unix_coverage_32bit_run_native_mpy_tests {
ci_unix_coverage_run_native_mpy_tests --arch x86
}

function ci_unix_nanbox_build {
ci_unix_build_helper VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1"
ci_unix_build_ffi_lib_helper gcc -m32
ci_unix_build_helper VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1" "${CI_UNIX_OPTS_X86[@]}"
ci_unix_build_ffi_lib_helper i686-linux-gnu-gcc
}

function ci_unix_nanbox_run_tests {
ci_unix_run_tests_full_no_native_helper nanbox
}

function ci_unix_longlong_build {
ci_unix_build_helper VARIANT=longlong "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}"
ci_unix_build_helper VARIANT=longlong "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" "${CI_UNIX_OPTS_X86[@]}"
patchelf --add-rpath "/usr/i686-linux-gnu/lib" ports/unix/build-longlong/micropython
}

function ci_unix_longlong_run_tests {
Expand Down Expand Up @@ -969,14 +973,14 @@ function ci_unix_qemu_riscv64_run_tests {
}

function ci_unix_repr_b_build {
ci_unix_build_helper "${CI_UNIX_OPTS_REPR_B[@]}"
ci_unix_build_ffi_lib_helper gcc -m32
ci_unix_build_helper "${CI_UNIX_OPTS_REPR_B[@]}" "${CI_UNIX_OPTS_X86[@]}"
ci_unix_build_ffi_lib_helper i686-linux-gnu-gcc
}

function ci_unix_repr_b_run_tests {
# ci_unix_run_tests_full_no_native_helper is not used due to
# https://github.com/micropython/micropython/issues/18105
ci_unix_run_tests_helper "${CI_UNIX_OPTS_REPR_B[@]}"
ci_unix_run_tests_helper "${CI_UNIX_OPTS_REPR_B[@]}" "${CI_UNIX_OPTS_X86[@]}"
}

########################################################################################
Expand Down
Loading