This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new efc1bf710 interpreters/python: Add Python's port to NuttX
efc1bf710 is described below
commit efc1bf710c8be1e0f0ae5e1bf2b292f8b57076a6
Author: Tiago Medicci <[email protected]>
AuthorDate: Wed Dec 4 16:48:38 2024 -0300
interpreters/python: Add Python's port to NuttX
This is the NuttX's port of Python (cpython)!
Initial support of Python includes building the Python's static
library and the `python` (Programs/python.c) application. Python's
modules are stored in `pyc` (byte-code file) and loaded as needed
from flash.
---
interpreters/python/.gitignore | 6 +
interpreters/python/Kconfig | 58 +++++++
interpreters/python/Make.defs | 30 ++++
interpreters/python/Makefile | 172 +++++++++++++++++++
interpreters/python/Setup.local | 50 ++++++
interpreters/python/config.site | 21 +++
interpreters/python/mount_modules.c | 132 ++++++++++++++
...-workaround-newlib-resource.h-limitations.patch | 29 ++++
...-uint32_t-unsigned-int-type-mismatch-issu.patch | 151 ++++++++++++++++
...assets.py-for-generating-an-archive-of-py.patch | 42 +++++
.../0004-recognize-nuttx-as-a-supported-OS.patch | 60 +++++++
...ix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch | 189 +++++++++++++++++++++
...name-to-avoid-conflict-with-nuttx-unused_.patch | 168 ++++++++++++++++++
.../python/patch/0007-undef-atexit_register.patch | 29 ++++
.../python/patch/0008-declare-struct-timeval.patch | 27 +++
...tx-sys-select-header-to-define-FD_SETSIZE.patch | 27 +++
...-the-d_ino-member-of-the-structure-dirent.patch | 173 +++++++++++++++++++
17 files changed, 1364 insertions(+)
diff --git a/interpreters/python/.gitignore b/interpreters/python/.gitignore
new file mode 100644
index 000000000..ad58719cd
--- /dev/null
+++ b/interpreters/python/.gitignore
@@ -0,0 +1,6 @@
+/*.zip
+/build/
+/install/
+/Python/
+/romfs_cpython_modules.h
+/romfs_cpython_modules.img
diff --git a/interpreters/python/Kconfig b/interpreters/python/Kconfig
new file mode 100644
index 000000000..da20c8ec4
--- /dev/null
+++ b/interpreters/python/Kconfig
@@ -0,0 +1,58 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config INTERPRETER_CPYTHON
+ tristate "CPython"
+ depends on LIB_ZLIB
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ Enable the CPython port to NuttX. This is a port of the Python
+ interpreter to NuttX. Initially, it is tweaked to work with the
+ RISC-V QEMU virtual board (`rv-virt`).
+
+if INTERPRETER_CPYTHON
+
+config INTERPRETER_CPYTHON_VERSION
+ string "Python Version"
+ default "3.13.0"
+
+config INTERPRETER_CPYTHON_STACKSIZE
+ int "CPython stack size"
+ default 307200
+ ---help---
+ This is the stack size allocated when the CPython task runs.
+
+config INTERPRETER_CPYTHON_PRIORITY
+ int "CPython task priority"
+ default 150
+ ---help---
+ This is the priority of the CPython task.
+
+config INTERPRETER_CPYTHON_PROGNAME
+ string "CPython name"
+ default "python"
+ ---help---
+ This is the name of the program that will be used from the nsh.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_STACKSIZE
+ int "CPython's Modules Mount stack size"
+ default 4096
+ ---help---
+ This is the stack size allocated when the CPython's Modules
Mount task runs.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_PRIORITY
+ int "CPython's Modules Mount task priority"
+ default 150
+ ---help---
+ This is the priority of the CPython's Modules Mount task.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_PROGNAME
+ string "CPython's Modules Mount app name"
+ default "python_mount_modules"
+ ---help---
+ This is the name of the program that will be used from the nsh.
+
+endif
diff --git a/interpreters/python/Make.defs b/interpreters/python/Make.defs
new file mode 100644
index 000000000..a1aecbdb4
--- /dev/null
+++ b/interpreters/python/Make.defs
@@ -0,0 +1,30 @@
+############################################################################
+# apps/interpreters/python/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_INTERPRETER_CPYTHON),)
+
+CPYTHON_VERSION = $(patsubst "%",%,$(strip
$(CONFIG_INTERPRETER_CPYTHON_VERSION)))
+CPYTHON_VERSION_MINOR=$(basename $(CPYTHON_VERSION))
+
+EXTRA_LIBPATHS += -L$(APPDIR)/interpreters/python/install/target
+EXTRA_LIBS += -lpython$(CPYTHON_VERSION_MINOR)
+
+CONFIGURED_APPS += $(APPDIR)/interpreters/python
+endif
diff --git a/interpreters/python/Makefile b/interpreters/python/Makefile
new file mode 100644
index 000000000..80db1722e
--- /dev/null
+++ b/interpreters/python/Makefile
@@ -0,0 +1,172 @@
+############################################################################
+# apps/interpreters/python/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+CPYTHON_URL ?= "https://github.com/python/cpython/archive"
+CPYTHON_VERSION = $(patsubst "%",%,$(strip
$(CONFIG_INTERPRETER_CPYTHON_VERSION)))
+CPYTHON_VERSION_MINOR=$(basename $(CPYTHON_VERSION))
+CPYTHON_ZIP = v$(CPYTHON_VERSION).zip
+
+CPYTHON_UNPACKNAME = Python
+UNPACK ?= unzip -q -o
+
+MACHDEP=nuttx
+CONFIG_SITE=${CURDIR}/config.site
+CPYTHON_PATH=$(CURDIR)/$(CPYTHON_UNPACKNAME)
+
+BUILDIR=$(CURDIR)/build
+INSTALLDIR=$(CURDIR)/install
+HOSTBUILD=$(BUILDIR)/host
+HOSTINSTALL=$(INSTALLDIR)/host
+HOSTPYTHON=$(HOSTINSTALL)/bin/python3
+TARGETBUILD=$(BUILDIR)/target
+TARGETINSTALL=$(INSTALLDIR)/target
+TARGETLIBPYTHON=$(TARGETINSTALL)/libpython$(CPYTHON_VERSION_MINOR).a
+TARGETMODULESPACK=$(TARGETBUILD)/lib/python$(shell echo
$(CPYTHON_VERSION_MINOR) | tr -d .).zip
+TARGETMODULES=$(TARGETINSTALL)/lib/
+
+DEPPATH += --dep-path $(CPYTHON_UNPACKNAME)$(DELIM)Programs
+VPATH += :$(CPYTHON_UNPACKNAME)$(DELIM)Programs
+
+$(CPYTHON_ZIP):
+ @echo "Downloading: $(CPYTHON_URL)/$(CPYTHON_ZIP)"
+ $(Q) $(call DOWNLOAD,$(CPYTHON_URL),$(CPYTHON_ZIP))
+
+$(CPYTHON_UNPACKNAME): $(CPYTHON_ZIP)
+ @echo "Unpacking: $(CPYTHON_ZIP) -> $(CPYTHON_UNPACKNAME)"
+ $(Q) $(UNPACK) $(CPYTHON_ZIP)
+ $(Q) mv cpython-$(CPYTHON_VERSION) $(CPYTHON_UNPACKNAME)
+ @echo "Patching $(CPYTHON_UNPACKNAME)"
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0001-workaround-newlib-resource.h-limitations.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0004-recognize-nuttx-as-a-supported-OS.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0007-undef-atexit_register.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0008-declare-struct-timeval.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
+ $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) <
patch$(DELIM)0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
+
+$(HOSTPYTHON):
+ mkdir -p $(HOSTBUILD)
+ mkdir -p $(HOSTINSTALL)
+ $(Q) ( \
+ cd $(HOSTBUILD) && $(CPYTHON_PATH)/configure \
+ --with-pydebug \
+ --prefix=$(HOSTINSTALL) \
+ )
+ $(MAKE) -C $(HOSTBUILD) install
+
+# For the Python's `configure` script, please consider the following
+# when building for NuttX:
+#
+# Use sed to remove optimization flags from NuttX's CFLAGS because
+# Python's configure script requires them in OPT. Having the flags in
+# both places causes a conflict.
+#
+# Also, use -O0 for OPT because -Os is causing problems in
+# Python/Modules/getpath.c (issue will be filed soon to track this
+# problem).
+
+$(TARGETBUILD)/Makefile: $(HOSTPYTHON)
+ $(Q) mkdir -p $(TARGETBUILD)/Modules
+ $(Q) mkdir -p $(TARGETMODULES)/python$(CPYTHON_VERSION_MINOR)
+ $(Q) ( cp Setup.local $(TARGETBUILD)/Modules/Setup.local )
+ $(Q) ( \
+ cd $(TARGETBUILD); \
+ CFLAGS="$(CFLAGS)"; \
+ ARCH=$(CONFIG_ARCH); \
+ ARCH_CHIP=$(CONFIG_ARCH_CHIP); \
+ ARCH="$${ARCH//-/}"; \
+ ARCH_CHIP="$${ARCH_CHIP//-/}"; \
+ CFLAGS="$$(echo "$${CFLAGS}" | sed 's/-Os //')" \
+ CC="$(CC)" \
+ CXX="$(CXX)" \
+ AR="$(AR)" \
+ ARFLAGS=" " \
+ MACHDEP="$(MACHDEP)" \
+ OPT="-g -O0 -Wall" \
+ CONFIG_SITE="$(CONFIG_SITE)" \
+ $(CPYTHON_PATH)/configure \
+ --prefix=${TARGETINSTALL} \
+ --disable-shared \
+ --host=$${ARCH}-$${ARCH_CHIP}-nuttx \
+ --build=$(shell $(CPYTHON_PATH)/config.guess) \
+ --with-build-python=${HOSTPYTHON} \
+ --without-mimalloc \
+ --without-pymalloc \
+ --disable-test-modules \
+ )
+
+$(TARGETLIBPYTHON): $(TARGETBUILD)/Makefile
+ $(MAKE) -C $(TARGETBUILD) regen-frozen
+ $(MAKE) -C $(TARGETBUILD) libpython$(CPYTHON_VERSION_MINOR).a
wasm_stdlib
+ $(Q) ( cp $(TARGETBUILD)/libpython$(CPYTHON_VERSION_MINOR).a
$(TARGETLIBPYTHON) )
+ $(Q) $(UNPACK) $(TARGETMODULESPACK) -d
$(TARGETMODULES)/python$(CPYTHON_VERSION_MINOR)
+
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Include
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Test
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Include$(DELIM)internal
+CFLAGS += ${INCDIR_PREFIX}$(APPDIR)$(DELIM)system
+CFLAGS += ${INCDIR_PREFIX}$(APPDIR)$(DELIM)system$(DELIM)zlib$(DELIM)zlib
+CFLAGS += ${INCDIR_PREFIX}$(TARGETBUILD)
+
+MODULE = $(CONFIG_INTERPRETER_CPYTHON)
+
+PROGNAME += $(CONFIG_INTERPRETER_CPYTHON_PROGNAME)
+PRIORITY += $(CONFIG_INTERPRETER_CPYTHON_PRIORITY)
+STACKSIZE += $(CONFIG_INTERPRETER_CPYTHON_STACKSIZE)
+
+MAINSRC += python.c
+
+PROGNAME += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_PROGNAME)
+PRIORITY += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_PRIORITY)
+STACKSIZE += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_STACKSIZE)
+
+MAINSRC += mount_modules.c
+
+checkgenromfs:
+ @genromfs -h 1>/dev/null 2>&1 || { \
+ echo "Host executable genromfs not available in PATH"; \
+ echo "You may need to download in from https://romfs.sourceforge.net/"; \
+ exit 1; \
+ }
+
+romfs_cpython_modules.img : $(TARGETLIBPYTHON) checkgenromfs
+ @genromfs -f $@ -d $(TARGETMODULES) -V "ROMFS_Test" || { echo "genromfs
failed" ; exit 1 ; }
+
+romfs_cpython_modules.h : romfs_cpython_modules.img
+ @xxd -i $< >$@ || { echo "xxd of $< failed" ; exit 1 ; }
+
+context:: $(CPYTHON_UNPACKNAME)
+
+depend:: romfs_cpython_modules.h
+
+distclean::
+ $(call DELDIR, $(BUILDIR))
+ $(call DELDIR, $(INSTALLDIR))
+ $(call DELDIR, $(CPYTHON_UNPACKNAME))
+ $(call DELFILE, $(CPYTHON_ZIP))
+ $(call DELFILE, romfs_cpython_modules.img)
+ $(call DELFILE, romfs_cpython_modules.h)
+
+include $(APPDIR)/Application.mk
diff --git a/interpreters/python/Setup.local b/interpreters/python/Setup.local
new file mode 100644
index 000000000..beca9d666
--- /dev/null
+++ b/interpreters/python/Setup.local
@@ -0,0 +1,50 @@
+# This file gets copied into the Modules/ folder when building
+# newlib configurations which do not support dynamic library
+# loading.
+
+*disabled*
+_asyncio
+_blake2
+_bz2
+_codecs_cn
+_codecs_hk
+_codecs_iso2022
+_codecs_jp
+_codecs_kr
+_codecs_tw
+_ctypes
+_decimal
+_elementtree
+_hashlib
+_heapq
+_interpchannels
+_interpqueues
+_lsprof
+_lzma
+_md5
+_multibytecodec
+_sha1
+_sha2
+_sha2
+_sha3
+_sha3
+_socket
+_sqlite3
+_ssl
+_statistics
+_testbuffer
+_testcapi
+_testclinic
+_testclinic_limited
+_testexternalinspection
+_testinternalcapi
+_testlimitedcapi
+_uuid
+_xxtestfuzz
+_zoneinfo
+mmap
+pwd
+pyexpat
+readline
+resource
+xxsubtype
diff --git a/interpreters/python/config.site b/interpreters/python/config.site
new file mode 100644
index 000000000..d806ba564
--- /dev/null
+++ b/interpreters/python/config.site
@@ -0,0 +1,21 @@
+export ac_cv_file__dev_ptmx="no"
+export ac_cv_file__dev_ptc="no"
+export ac_cv_buggy_getaddrinfo="no"
+export ac_cv_func_getaddrinfo="yes"
+export ac_cv_pthread_is_default="yes"
+export ac_cv_func_acosh="yes"
+export ac_cv_func_asinh="yes"
+export ac_cv_func_atanh="yes"
+export ac_cv_func_erf="yes"
+export ac_cv_func_erfc="yes"
+export ac_cv_func_expm1="yes"
+export ac_cv_func_log1p="yes"
+export ac_cv_func_log2="yes"
+export ac_cv_func_clock_gettime="yes"
+export ac_cv_header_sys_syscall_h="no"
+export ac_cv_func_timegm="yes"
+export ac_cv_func_clock="yes"
+export ac_cv_func_fork="yes"
+export ac_cv_func_waitpid="yes"
+export ac_cv_func_pipe="yes"
+export MODULE_BUILDTYPE="static"
diff --git a/interpreters/python/mount_modules.c
b/interpreters/python/mount_modules.c
new file mode 100644
index 000000000..89a7bc377
--- /dev/null
+++ b/interpreters/python/mount_modules.c
@@ -0,0 +1,132 @@
+/****************************************************************************
+ * apps/interpreters/python/mount_modules.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/boardctl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <nuttx/drivers/ramdisk.h>
+
+#include "romfs_cpython_modules.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration settings */
+
+#ifndef CONFIG_CPYTHON_ROMFS_RAMDEVNO
+# define CONFIG_CPYTHON_ROMFS_RAMDEVNO 1
+#endif
+
+#ifndef CONFIG_CPYTHON_ROMFS_SECTORSIZE
+# define CONFIG_CPYTHON_ROMFS_SECTORSIZE 64
+#endif
+
+#ifndef CONFIG_CPYTHON_ROMFS_MOUNTPOINT
+# define CONFIG_CPYTHON_ROMFS_MOUNTPOINT "/usr/local/lib/"
+#endif
+
+#ifdef CONFIG_DISABLE_MOUNTPOINT
+# error "Mountpoint support is disabled"
+#endif
+
+#ifndef CONFIG_FS_ROMFS
+# error "ROMFS support not enabled"
+#endif
+
+#define NSECTORS(b)
(((b)+CONFIG_CPYTHON_ROMFS_SECTORSIZE-1)/CONFIG_CPYTHON_ROMFS_SECTORSIZE)
+#define STR_RAMDEVNO(m) #m
+#define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m)
+#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_CPYTHON_ROMFS_RAMDEVNO)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mount_modules
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+ int ret;
+ struct boardioc_romdisk_s desc;
+
+ /* Create a RAM disk for the test */
+
+ desc.minor = CONFIG_CPYTHON_ROMFS_RAMDEVNO; /* Minor device
number of the ROM disk. */
+ desc.nsectors = NSECTORS(romfs_cpython_modules_img_len); /* The number of
sectors in the ROM disk */
+ desc.sectsize = CONFIG_CPYTHON_ROMFS_SECTORSIZE; /* The size of one
sector in bytes */
+ desc.image = (FAR uint8_t *)romfs_cpython_modules_img; /* File system
image */
+
+ ret = boardctl(BOARDIOC_ROMDISK, (uintptr_t)&desc);
+
+ if (ret < 0)
+ {
+ printf("ERROR: Failed to create RAM disk: %s\n", strerror(errno));
+ return 1;
+ }
+
+ /* Mount the test file system */
+
+ printf("Mounting ROMFS filesystem at target=%s with source=%s\n",
+ CONFIG_CPYTHON_ROMFS_MOUNTPOINT, MOUNT_DEVNAME);
+
+ ret = mount(MOUNT_DEVNAME, CONFIG_CPYTHON_ROMFS_MOUNTPOINT, "romfs",
+ MS_RDONLY, NULL);
+ if (ret < 0)
+ {
+ printf("ERROR: Mount failed: %s\n", strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
diff --git
a/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch
b/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch
new file mode 100644
index 000000000..dfb9d437a
--- /dev/null
+++
b/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch
@@ -0,0 +1,29 @@
+From b2ac42cefa3747c7f7a9066fceed834286e829af Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Tue, 22 Oct 2024 23:58:17 +0200
+Subject: [PATCH 01/10] workaround newlib resource.h limitations
+
+configure script checks if resource.h is available but doesn't check
+if it defines all the necessary functions.
+
+Temporary workaround until these functions are added to IDF.
+---
+ Modules/faulthandler.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
+index b62362f2777..327d883f94e 100644
+--- a/Modules/faulthandler.c
++++ b/Modules/faulthandler.c
+@@ -968,7 +968,7 @@ faulthandler_suppress_crash_report(void)
+ SetErrorMode(mode | SEM_NOGPFAULTERRORBOX);
+ #endif
+
+-#ifdef HAVE_SYS_RESOURCE_H
++#if 0 && defined(HAVE_SYS_RESOURCE_H)
+ struct rlimit rl;
+
+ /* Disable creation of core dump */
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
b/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
new file mode 100644
index 000000000..0bf12755a
--- /dev/null
+++
b/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
@@ -0,0 +1,151 @@
+From 036b39478c2419af1e0a64763b9ac741cf886387 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:48:49 +0200
+Subject: [PATCH 02/10] fix various uint32_t/'unsigned int' type mismatch
+ issues
+
+In a few places existing code assumes that uint32_t == unsigned int.
+Since in Xtensa and RISC-V bare metal toolchains uint32_t is instead
+'unsigned long', the original code fails to build.
+---
+ Modules/zlibmodule.c | 28 ++++++++++++++--------------
+ Objects/typeobject.c | 2 +-
+ 2 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
+index b115f67f228..034a9420b16 100644
+--- a/Modules/zlibmodule.c
++++ b/Modules/zlibmodule.c
+@@ -28,13 +28,13 @@
+ On failure, return -1 */
+ static inline Py_ssize_t
+ OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length,
+- Bytef **next_out, uint32_t *avail_out)
++ Bytef **next_out, unsigned int *avail_out)
+ {
+ Py_ssize_t allocated;
+
+ allocated = _BlocksOutputBuffer_InitAndGrow(
+ buffer, max_length, (void**) next_out);
+- *avail_out = (uint32_t) allocated;
++ *avail_out = (unsigned) allocated;
+ return allocated;
+ }
+
+@@ -42,24 +42,24 @@ OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer,
Py_ssize_t max_length,
+ On failure, return -1 */
+ static inline Py_ssize_t
+ OutputBuffer_Grow(_BlocksOutputBuffer *buffer,
+- Bytef **next_out, uint32_t *avail_out)
++ Bytef **next_out, unsigned int *avail_out)
+ {
+ Py_ssize_t allocated;
+
+ allocated = _BlocksOutputBuffer_Grow(
+ buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+- *avail_out = (uint32_t) allocated;
++ *avail_out = (unsigned int) allocated;
+ return allocated;
+ }
+
+ static inline Py_ssize_t
+-OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, uint32_t avail_out)
++OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, unsigned int avail_out)
+ {
+ return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out);
+ }
+
+ static inline PyObject *
+-OutputBuffer_Finish(_BlocksOutputBuffer *buffer, uint32_t avail_out)
++OutputBuffer_Finish(_BlocksOutputBuffer *buffer, unsigned int avail_out)
+ {
+ return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out);
+ }
+@@ -97,7 +97,7 @@ typedef struct {
+ static inline Py_ssize_t
+ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer *buffer, _Uint32Window
*window,
+ Py_ssize_t init_size,
+- Bytef **next_out, uint32_t *avail_out)
++ Bytef **next_out, unsigned int *avail_out)
+ {
+ Py_ssize_t allocated = _BlocksOutputBuffer_InitWithSize(
+ buffer, init_size, (void**) next_out);
+@@ -105,7 +105,7 @@ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer
*buffer, _Uint32Window *wind
+ if (allocated >= 0) {
+ // the UINT32_MAX sliding window
+ Py_ssize_t window_size = Py_MIN((size_t)allocated, UINT32_MAX);
+- *avail_out = (uint32_t) window_size;
++ *avail_out = (unsigned int) window_size;
+
+ window->left_bytes = allocated - window_size;
+ window->next_posi = *next_out + window_size;
+@@ -119,7 +119,7 @@ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer
*buffer, _Uint32Window *wind
+ On failure, return value < 0 */
+ static inline Py_ssize_t
+ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+- Bytef **next_out, uint32_t *avail_out)
++ Bytef **next_out, unsigned int *avail_out)
+ {
+ Py_ssize_t allocated;
+
+@@ -136,7 +136,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer,
_Uint32Window *window,
+ Py_ssize_t window_size = Py_MIN((size_t)window->left_bytes,
UINT32_MAX);
+
+ *next_out = window->next_posi;
+- *avail_out = (uint32_t) window_size;
++ *avail_out = (unsigned int) window_size;
+
+ window->left_bytes -= window_size;
+ window->next_posi += window_size;
+@@ -148,7 +148,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer,
_Uint32Window *window,
+ // only the first block may > UINT32_MAX
+ allocated = _BlocksOutputBuffer_Grow(
+ buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+- *avail_out = (uint32_t) allocated;
++ *avail_out = (unsigned int) allocated;
+ return allocated;
+ }
+
+@@ -158,7 +158,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer,
_Uint32Window *window,
+ On failure, return NULL */
+ static inline PyObject *
+ OutputBuffer_WindowFinish(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+- uint32_t avail_out)
++ unsigned avail_out)
+ {
+ Py_ssize_t real_avail_out = (Py_ssize_t) avail_out + window->left_bytes;
+ return _BlocksOutputBuffer_Finish(buffer, real_avail_out);
+@@ -1398,7 +1398,7 @@ set_inflate_zdict_ZlibDecompressor(zlibstate *state,
ZlibDecompressor *self)
+ }
+
+ static Py_ssize_t
+-arrange_output_buffer_with_maximum(uint32_t *avail_out,
++arrange_output_buffer_with_maximum(unsigned int *avail_out,
+ uint8_t **next_out,
+ PyObject **buffer,
+ Py_ssize_t length,
+@@ -1430,7 +1430,7 @@ arrange_output_buffer_with_maximum(uint32_t *avail_out,
+ }
+ }
+
+- *avail_out = (uint32_t)Py_MIN((size_t)(length - occupied), UINT32_MAX);
++ *avail_out = (unsigned)Py_MIN((size_t)(length - occupied), UINT32_MAX);
+ *next_out = (uint8_t *)PyBytes_AS_STRING(*buffer) + occupied;
+
+ return length;
+diff --git a/Objects/typeobject.c b/Objects/typeobject.c
+index c911c302003..9c640e0ab65 100644
+--- a/Objects/typeobject.c
++++ b/Objects/typeobject.c
+@@ -5140,7 +5140,7 @@ is_dunder_name(PyObject *name)
+ static PyObject *
+ update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int
version_tag, PyObject *value)
+ {
+- _Py_atomic_store_uint32_relaxed(&entry->version, version_tag);
++ _Py_atomic_store_uint32_relaxed((uint32_t*) &entry->version, version_tag);
+ _Py_atomic_store_ptr_relaxed(&entry->value, value); /* borrowed */
+ assert(_PyASCIIObject_CAST(name)->hash != -1);
+ OBJECT_STAT_INC_COND(type_cache_collisions, entry->name != Py_None &&
entry->name != name);
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
b/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
new file mode 100644
index 000000000..f8e03a2cf
--- /dev/null
+++
b/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
@@ -0,0 +1,42 @@
+From 4af7a9b726ca2c8ac330b51f98acf0a103f6fa71 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:54:39 +0200
+Subject: [PATCH 03/10] reuse wasm_assets.py for generating an archive of
+ python lib dir
+
+wasm_assets.py is a useful script to prepare the smallest possible
+package of pre-compiled python stdlib modules. There is very little
+wasm-specific there.
+
+This patch adds nuttx to the supported OS list in the script, as well
+as fixes what I think is a bug in path calculation.
+
+Co-authored-by: Tiago Medicci Serrano <[email protected]>
+---
+ Tools/wasm/wasm_assets.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py
+index ffa5e303412..381d4819c39 100755
+--- a/Tools/wasm/wasm_assets.py
++++ b/Tools/wasm/wasm_assets.py
+@@ -99,6 +99,7 @@
+ "_sysconfigdata__emscripten_wasm32-emscripten",
+ "_sysconfigdata__wasi_wasm32-wasi",
+ "_sysconfigdata__wasi_wasm64-wasi",
++ "_sysconfigdata__nuttx_"
+ )
+
+
+@@ -203,7 +204,7 @@ def main() -> None:
+ relative_prefix = args.prefix.relative_to(pathlib.Path("/"))
+ args.srcdir = SRCDIR
+ args.srcdir_lib = SRCDIR_LIB
+- args.wasm_root = args.buildroot / relative_prefix
++ args.wasm_root = args.buildroot #/ relative_prefix
+ args.wasm_stdlib_zip = args.wasm_root / WASM_STDLIB_ZIP
+ args.wasm_stdlib = args.wasm_root / WASM_STDLIB
+ args.wasm_dynload = args.wasm_root / WASM_DYNLOAD
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch
b/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch
new file mode 100644
index 000000000..6d8531ce6
--- /dev/null
+++ b/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch
@@ -0,0 +1,60 @@
+From 1bb8d824a4b4e4b38c3541b7c26c5d71f0970266 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:55:53 +0200
+Subject: [PATCH 04/10] recognize *-*-nuttx as a supported OS
+
+cpython's configure script bails out when cross-compiling for an
+unknown OS, so we have to add "nuttx" to the list, even though it
+is not used almost anywhere else.
+
+Co-authored-by: Tiago Medicci Serrano <[email protected]>
+---
+ config.sub | 2 +-
+ configure | 3 +++
+ configure.ac | 3 +++
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/config.sub b/config.sub
+index 1bb6a05dc11..2a87d3e0ddb 100755
+--- a/config.sub
++++ b/config.sub
+@@ -1769,7 +1769,7 @@ case $os in
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+- | fiwix* | mlibc* | cos* | mbr* | ironclad* )
++ | fiwix* | mlibc* | cos* | mbr* | ironclad* | nuttx* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff --git a/configure b/configure
+index 7cdd386c387..6da5e9f3832 100755
+--- a/configure
++++ b/configure
+@@ -4527,6 +4527,9 @@ printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
+ wasm32-*-* | wasm64-*-*)
+ _host_ident=$host_cpu
+ ;;
++ *-*-nuttx*)
++ _host_ident=$host_cpu
++ ;;
+ *)
+ # for now, limit cross builds to known configurations
+ MACHDEP="unknown"
+diff --git a/configure.ac b/configure.ac
+index 24e28a1e2de..80d6738fab5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -777,6 +777,9 @@ if test "$cross_compiling" = yes; then
+ wasm32-*-* | wasm64-*-*)
+ _host_ident=$host_cpu
+ ;;
++ *-*-nuttx*)
++ _host_ident=$host_cpu
++ ;;
+ *)
+ # for now, limit cross builds to known configurations
+ MACHDEP="unknown"
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
b/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
new file mode 100644
index 000000000..cf25d88c2
--- /dev/null
+++
b/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
@@ -0,0 +1,189 @@
+From cd8af3cbc9881e5a4a7c0644c8844478c8d0245d Mon Sep 17 00:00:00 2001
+From: Eric Snow <[email protected]>
+Date: Tue, 13 Aug 2024 14:44:57 -0600
+Subject: [PATCH 05/10] gh-122907: Fix Builds Without HAVE_DYNAMIC_LOADING Set
+ (gh-122952)
+
+As of 529a160 (gh-118204), building with HAVE_DYNAMIC_LOADING stopped working.
This is a minimal fix just to get builds working again. There are actually a
number of long-standing deficiencies with HAVE_DYNAMIC_LOADING builds that need
to be resolved separately.
+(cherry picked from commit ee1b8ce26e700350e47a5f65201097121c41912e)
+
+Co-authored-by: Eric Snow <[email protected]>
+---
+ Include/internal/pycore_importdl.h | 4 ++++
+ Lib/importlib/_bootstrap_external.py | 16 ++++++++--------
+ ...024-08-12-11-19-37.gh-issue-122907.q68096.rst | 3 +++
+ Python/importdl.c | 12 ++++++++----
+ Tools/build/check_extension_modules.py | 9 +++++++++
+ 5 files changed, 32 insertions(+), 12 deletions(-)
+ create mode 100644
Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+
+diff --git a/Include/internal/pycore_importdl.h
b/Include/internal/pycore_importdl.h
+index e5f222b371a..525a16f6b97 100644
+--- a/Include/internal/pycore_importdl.h
++++ b/Include/internal/pycore_importdl.h
+@@ -56,9 +56,11 @@ extern int _Py_ext_module_loader_info_init_for_core(
+ extern int _Py_ext_module_loader_info_init_for_builtin(
+ struct _Py_ext_module_loader_info *p_info,
+ PyObject *name);
++#ifdef HAVE_DYNAMIC_LOADING
+ extern int _Py_ext_module_loader_info_init_from_spec(
+ struct _Py_ext_module_loader_info *info,
+ PyObject *spec);
++#endif
+
+ /* The result from running an extension module's init function. */
+ struct _Py_ext_module_loader_result {
+@@ -87,9 +89,11 @@ extern void _Py_ext_module_loader_result_apply_error(
+
+ /* The module init function. */
+ typedef PyObject *(*PyModInitFunction)(void);
++#ifdef HAVE_DYNAMIC_LOADING
+ extern PyModInitFunction _PyImport_GetModInitFunc(
+ struct _Py_ext_module_loader_info *info,
+ FILE *fp);
++#endif
+ extern int _PyImport_RunModInitFunc(
+ PyModInitFunction p0,
+ struct _Py_ext_module_loader_info *info,
+diff --git a/Lib/importlib/_bootstrap_external.py
b/Lib/importlib/_bootstrap_external.py
+index 7742855e8b2..d8c61c92558 100644
+--- a/Lib/importlib/_bootstrap_external.py
++++ b/Lib/importlib/_bootstrap_external.py
+@@ -1793,14 +1793,14 @@ def _get_supported_file_loaders():
+
+ Each item is a tuple (loader, suffixes).
+ """
+- if sys.platform in {"ios", "tvos", "watchos"}:
+- extension_loaders = [(AppleFrameworkLoader, [
+- suffix.replace(".so", ".fwork")
+- for suffix in _imp.extension_suffixes()
+- ])]
+- else:
+- extension_loaders = []
+- extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes()))
++ extension_loaders = []
++ if hasattr(_imp, 'create_dynamic'):
++ if sys.platform in {"ios", "tvos", "watchos"}:
++ extension_loaders = [(AppleFrameworkLoader, [
++ suffix.replace(".so", ".fwork")
++ for suffix in _imp.extension_suffixes()
++ ])]
++ extension_loaders.append((ExtensionFileLoader,
_imp.extension_suffixes()))
+ source = SourceFileLoader, SOURCE_SUFFIXES
+ bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
+ return extension_loaders + [source, bytecode]
+diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+new file mode 100644
+index 00000000000..88c872f4ef4
+--- /dev/null
++++
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+@@ -0,0 +1,3 @@
++Building with ``HAVE_DYNAMIC_LOADING`` now works as well as it did in 3.12.
++Existing deficiences will be addressed separately.
++(See https://github.com/python/cpython/issues/122950.)
+diff --git a/Python/importdl.c b/Python/importdl.c
+index 7c42d37283c..b1a6fcc8223 100644
+--- a/Python/importdl.c
++++ b/Python/importdl.c
+@@ -8,6 +8,8 @@
+ #include "pycore_pystate.h"
+ #include "pycore_runtime.h"
+
++#include "pycore_importdl.h"
++
+ /* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is
+ supported on this platform. configure will then compile and link in one
+ of the dynload_*.c files, as appropriate. We will call a function in
+@@ -15,8 +17,6 @@
+ */
+ #ifdef HAVE_DYNAMIC_LOADING
+
+-#include "pycore_importdl.h"
+-
+ #ifdef MS_WINDOWS
+ extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
+ const char *shortname,
+@@ -28,6 +28,8 @@ extern dl_funcptr _PyImport_FindSharedFuncptr(const char
*prefix,
+ const char *pathname, FILE *fp);
+ #endif
+
++#endif /* HAVE_DYNAMIC_LOADING */
++
+
+ /***********************************/
+ /* module info to use when loading */
+@@ -205,6 +207,7 @@ _Py_ext_module_loader_info_init_for_core(
+ return 0;
+ }
+
++#ifdef HAVE_DYNAMIC_LOADING
+ int
+ _Py_ext_module_loader_info_init_from_spec(
+ struct _Py_ext_module_loader_info *p_info,
+@@ -226,6 +229,7 @@ _Py_ext_module_loader_info_init_from_spec(
+ Py_DECREF(filename);
+ return err;
+ }
++#endif /* HAVE_DYNAMIC_LOADING */
+
+
+ /********************************/
+@@ -372,6 +376,7 @@ _Py_ext_module_loader_result_apply_error(
+ /* getting/running the module init function */
+ /********************************************/
+
++#ifdef HAVE_DYNAMIC_LOADING
+ PyModInitFunction
+ _PyImport_GetModInitFunc(struct _Py_ext_module_loader_info *info,
+ FILE *fp)
+@@ -406,6 +411,7 @@ _PyImport_GetModInitFunc(struct _Py_ext_module_loader_info
*info,
+
+ return (PyModInitFunction)exportfunc;
+ }
++#endif /* HAVE_DYNAMIC_LOADING */
+
+ int
+ _PyImport_RunModInitFunc(PyModInitFunction p0,
+@@ -513,5 +519,3 @@ _PyImport_RunModInitFunc(PyModInitFunction p0,
+ p_res->err = &p_res->_err;
+ return -1;
+ }
+-
+-#endif /* HAVE_DYNAMIC_LOADING */
+diff --git a/Tools/build/check_extension_modules.py
b/Tools/build/check_extension_modules.py
+index 7de35b499da..66b2a262e11 100644
+--- a/Tools/build/check_extension_modules.py
++++ b/Tools/build/check_extension_modules.py
+@@ -27,6 +27,7 @@
+ import sys
+ import sysconfig
+ import warnings
++import _imp
+
+ from importlib._bootstrap import _load as bootstrap_load
+ from importlib.machinery import BuiltinImporter, ExtensionFileLoader,
ModuleSpec
+@@ -154,6 +155,11 @@ def __init__(self, cross_compiling: bool = False, strict:
bool = False):
+ self.notavailable = []
+
+ def check(self):
++ if not hasattr(_imp, 'create_dynamic'):
++ logger.warning(
++ ('Dynamic extensions not supported '
++ '(HAVE_DYNAMIC_LOADING not defined)'),
++ )
+ for modinfo in self.modules:
+ logger.debug("Checking '%s' (%s)", modinfo.name,
self.get_location(modinfo))
+ if modinfo.state == ModuleState.DISABLED:
+@@ -415,6 +421,9 @@ def check_module_import(self, modinfo: ModuleInfo):
+ logger.error("%s failed to import: %s", modinfo.name, e)
+ raise
+ except Exception as e:
++ if not hasattr(_imp, 'create_dynamic'):
++ logger.warning("Dynamic extension '%s' ignored", modinfo.name)
++ return
+ logger.exception("Importing extension '%s' failed!", modinfo.name)
+ raise
+
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
b/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
new file mode 100644
index 000000000..641233bf4
--- /dev/null
+++
b/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
@@ -0,0 +1,168 @@
+From d424766bff74fb34a80a09c6e2ed8d9b40350bb8 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:20:36 -0300
+Subject: [PATCH 06/10] change var name to avoid conflict with nuttx
+ unused_data macro
+
+---
+ Modules/zlibmodule.c | 42 +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
+index 034a9420b16..595d4ad32e9 100644
+--- a/Modules/zlibmodule.c
++++ b/Modules/zlibmodule.c
+@@ -213,7 +213,7 @@ typedef struct
+ {
+ PyObject_HEAD
+ z_stream zst;
+- PyObject *unused_data;
++ PyObject *unused_data_var;
+ PyObject *unconsumed_tail;
+ char eof;
+ bool is_initialised;
+@@ -267,8 +267,8 @@ newcompobject(PyTypeObject *type)
+ self->eof = 0;
+ self->is_initialised = 0;
+ self->zdict = NULL;
+- self->unused_data = PyBytes_FromStringAndSize("", 0);
+- if (self->unused_data == NULL) {
++ self->unused_data_var = PyBytes_FromStringAndSize("", 0);
++ if (self->unused_data_var == NULL) {
+ Py_DECREF(self);
+ return NULL;
+ }
+@@ -708,7 +708,7 @@ Dealloc(compobject *self)
+ {
+ PyObject *type = (PyObject *)Py_TYPE(self);
+ PyThread_free_lock(self->lock);
+- Py_XDECREF(self->unused_data);
++ Py_XDECREF(self->unused_data_var);
+ Py_XDECREF(self->unconsumed_tail);
+ Py_XDECREF(self->zdict);
+ PyObject_Free(self);
+@@ -803,15 +803,15 @@ zlib_Compress_compress_impl(compobject *self,
PyTypeObject *cls,
+ }
+
+ /* Helper for objdecompress() and flush(). Saves any unconsumed input data in
+- self->unused_data or self->unconsumed_tail, as appropriate. */
++ self->unused_data_var or self->unconsumed_tail, as appropriate. */
+ static int
+ save_unconsumed_input(compobject *self, Py_buffer *data, int err)
+ {
+ if (err == Z_STREAM_END) {
+ /* The end of the compressed data has been reached. Store the leftover
+- input data in self->unused_data. */
++ input data in self->unused_data_var. */
+ if (self->zst.avail_in > 0) {
+- Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data);
++ Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data_var);
+ Py_ssize_t new_size, left_size;
+ PyObject *new_data;
+ left_size = (Byte *)data->buf + data->len - self->zst.next_in;
+@@ -824,10 +824,10 @@ save_unconsumed_input(compobject *self, Py_buffer *data,
int err)
+ if (new_data == NULL)
+ return -1;
+ memcpy(PyBytes_AS_STRING(new_data),
+- PyBytes_AS_STRING(self->unused_data), old_size);
++ PyBytes_AS_STRING(self->unused_data_var), old_size);
+ memcpy(PyBytes_AS_STRING(new_data) + old_size,
+ self->zst.next_in, left_size);
+- Py_SETREF(self->unused_data, new_data);
++ Py_SETREF(self->unused_data_var, new_data);
+ self->zst.avail_in = 0;
+ }
+ }
+@@ -1091,7 +1091,7 @@ zlib_Compress_copy_impl(compobject *self, PyTypeObject
*cls)
+ zlib_error(state, self->zst, err, "while copying compression object");
+ goto error;
+ }
+- Py_XSETREF(return_value->unused_data, Py_NewRef(self->unused_data));
++ Py_XSETREF(return_value->unused_data_var,
Py_NewRef(self->unused_data_var));
+ Py_XSETREF(return_value->unconsumed_tail,
Py_NewRef(self->unconsumed_tail));
+ Py_XSETREF(return_value->zdict, Py_XNewRef(self->zdict));
+ return_value->eof = self->eof;
+@@ -1176,7 +1176,7 @@ zlib_Decompress_copy_impl(compobject *self, PyTypeObject
*cls)
+ goto error;
+ }
+
+- Py_XSETREF(return_value->unused_data, Py_NewRef(self->unused_data));
++ Py_XSETREF(return_value->unused_data_var,
Py_NewRef(self->unused_data_var));
+ Py_XSETREF(return_value->unconsumed_tail,
Py_NewRef(self->unconsumed_tail));
+ Py_XSETREF(return_value->zdict, Py_XNewRef(self->zdict));
+ return_value->eof = self->eof;
+@@ -1341,7 +1341,7 @@ typedef struct {
+ z_stream zst;
+ PyObject *zdict;
+ PyThread_type_lock lock;
+- PyObject *unused_data;
++ PyObject *unused_data_var;
+ uint8_t *input_buffer;
+ Py_ssize_t input_buffer_size;
+ /* zst>avail_in is only 32 bit, so we store the true length
+@@ -1367,7 +1367,7 @@ ZlibDecompressor_dealloc(ZlibDecompressor *self)
+ inflateEnd(&self->zst);
+ }
+ PyMem_Free(self->input_buffer);
+- Py_CLEAR(self->unused_data);
++ Py_CLEAR(self->unused_data_var);
+ Py_CLEAR(self->zdict);
+ PyObject_Free(self);
+ Py_DECREF(type);
+@@ -1602,12 +1602,12 @@ decompress(ZlibDecompressor *self, uint8_t *data,
+ self->needs_input = 0;
+
+ if (self->avail_in_real > 0) {
+- PyObject *unused_data = PyBytes_FromStringAndSize(
++ PyObject *unused_data_var = PyBytes_FromStringAndSize(
+ (char *)self->zst.next_in, self->avail_in_real);
+- if (unused_data == NULL) {
++ if (unused_data_var == NULL) {
+ goto error;
+ }
+- Py_XSETREF(self->unused_data, unused_data);
++ Py_XSETREF(self->unused_data_var, unused_data_var);
+ }
+ }
+ else if (self->avail_in_real == 0) {
+@@ -1671,7 +1671,7 @@ was less than *max_length* bytes, or because
*max_length* was negative),
+
+ Attempting to decompress data after the end of stream is reached raises an
+ EOFError. Any data found after the end of the stream is ignored and saved in
+-the unused_data attribute.
++the unused_data_var attribute.
+ [clinic start generated code]*/
+
+ static PyObject *
+@@ -1739,8 +1739,8 @@ ZlibDecompressor__new__(PyTypeObject *cls,
+ self->zst.zfree = PyZlib_Free;
+ self->zst.next_in = NULL;
+ self->zst.avail_in = 0;
+- self->unused_data = PyBytes_FromStringAndSize(NULL, 0);
+- if (self->unused_data == NULL) {
++ self->unused_data_var = PyBytes_FromStringAndSize(NULL, 0);
++ if (self->unused_data_var == NULL) {
+ Py_CLEAR(self);
+ return NULL;
+ }
+@@ -1806,7 +1806,7 @@ static PyMethodDef ZlibDecompressor_methods[] = {
+
+ #define COMP_OFF(x) offsetof(compobject, x)
+ static PyMemberDef Decomp_members[] = {
+- {"unused_data", _Py_T_OBJECT, COMP_OFF(unused_data), Py_READONLY},
++ {"unused_data_var", _Py_T_OBJECT, COMP_OFF(unused_data_var),
Py_READONLY},
+ {"unconsumed_tail", _Py_T_OBJECT, COMP_OFF(unconsumed_tail), Py_READONLY},
+ {"eof", Py_T_BOOL, COMP_OFF(eof), Py_READONLY},
+ {NULL},
+@@ -1824,7 +1824,7 @@ PyDoc_STRVAR(ZlibDecompressor_needs_input_doc,
+ static PyMemberDef ZlibDecompressor_members[] = {
+ {"eof", Py_T_BOOL, offsetof(ZlibDecompressor, eof),
+ Py_READONLY, ZlibDecompressor_eof__doc__},
+- {"unused_data", Py_T_OBJECT_EX, offsetof(ZlibDecompressor, unused_data),
++ {"unused_data_var", Py_T_OBJECT_EX, offsetof(ZlibDecompressor,
unused_data_var),
+ Py_READONLY, ZlibDecompressor_unused_data__doc__},
+ {"needs_input", Py_T_BOOL, offsetof(ZlibDecompressor, needs_input),
Py_READONLY,
+ ZlibDecompressor_needs_input_doc},
+--
+2.46.1
+
diff --git a/interpreters/python/patch/0007-undef-atexit_register.patch
b/interpreters/python/patch/0007-undef-atexit_register.patch
new file mode 100644
index 000000000..266f704a9
--- /dev/null
+++ b/interpreters/python/patch/0007-undef-atexit_register.patch
@@ -0,0 +1,29 @@
+From 1b802bfd159a6a9766ca5834af90f55d54285b4b Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:22:04 -0300
+Subject: [PATCH 07/10] undef atexit_register
+
+Even if not built, nuttx/include/nuttx/atexit.h defines it and this
+causes conflicts.
+---
+ Modules/atexitmodule.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c
+index 297a8d74ba3..1fea72fbc99 100644
+--- a/Modules/atexitmodule.c
++++ b/Modules/atexitmodule.c
+@@ -175,6 +175,10 @@ Register a function to be executed upon normal program
termination\n\
+ \n\
+ func is returned to facilitate usage as a decorator.");
+
++#ifdef atexit_register
++# undef atexit_register
++#endif
++
+ static PyObject *
+ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
+ {
+--
+2.46.1
+
diff --git a/interpreters/python/patch/0008-declare-struct-timeval.patch
b/interpreters/python/patch/0008-declare-struct-timeval.patch
new file mode 100644
index 000000000..bb8d3cb43
--- /dev/null
+++ b/interpreters/python/patch/0008-declare-struct-timeval.patch
@@ -0,0 +1,27 @@
+From b40e89c190ec7c6b3b0116a3f7025ab13854398f Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:23:34 -0300
+Subject: [PATCH 08/10] declare struct timeval
+
+Otherwise, build will fail due to redefinition of _PyTime_FromTimeval
+---
+ Include/internal/pycore_time.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/Include/internal/pycore_time.h b/Include/internal/pycore_time.h
+index 205ac5d3781..c30e07f4b4a 100644
+--- a/Include/internal/pycore_time.h
++++ b/Include/internal/pycore_time.h
+@@ -58,9 +58,7 @@ extern "C" {
+ #endif
+
+
+-#ifdef __clang__
+ struct timeval;
+-#endif
+
+ #define _SIZEOF_PYTIME_T 8
+
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
b/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
new file mode 100644
index 000000000..b52b76be1
--- /dev/null
+++
b/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
@@ -0,0 +1,27 @@
+From 9a32a300c95e0061220d2608a014c7fa39dedab3 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Thu, 14 Nov 2024 13:44:49 -0300
+Subject: [PATCH 09/10] include nuttx sys/select header to define FD_SETSIZE
+
+---
+ Modules/selectmodule.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
+index 5bd9b7732a4..e9fab839122 100644
+--- a/Modules/selectmodule.c
++++ b/Modules/selectmodule.c
+@@ -63,6 +63,10 @@ extern void bzero(void *, int);
+ #include <sys/types.h>
+ #endif
+
++#ifdef HAVE_SYS_SELECT_H
++#include <sys/select.h>
++#endif
++
+ #ifdef MS_WINDOWS
+ # ifndef WIN32_LEAN_AND_MEAN
+ # define WIN32_LEAN_AND_MEAN
+--
+2.46.1
+
diff --git
a/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
b/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
new file mode 100644
index 000000000..d65b1f287
--- /dev/null
+++
b/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
@@ -0,0 +1,173 @@
+From 4f6a1db85c56df378dc3856ed95a0a7342f44d89 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Tue, 3 Dec 2024 17:18:50 -0300
+Subject: [PATCH 10/10] check for the d_ino member of the structure dirent
+
+---
+ Modules/posixmodule.c | 18 ++++++++++++++++--
+ configure | 43 +++++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 5 +++++
+ pyconfig.h.in | 3 +++
+ 4 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
+index 51e34b5f4b7..2aa507aa942 100644
+--- a/Modules/posixmodule.c
++++ b/Modules/posixmodule.c
+@@ -15522,7 +15522,9 @@ typedef struct {
+ #ifdef HAVE_DIRENT_D_TYPE
+ unsigned char d_type;
+ #endif
++#ifdef HAVE_DIRENT_D_INO
+ ino_t d_ino;
++#endif
+ int dir_fd;
+ #endif
+ } DirEntry;
+@@ -15821,6 +15823,7 @@ os.DirEntry.inode
+ Return inode of the entry; cached per entry.
+ [clinic start generated code]*/
+
++#ifdef HAVE_DIRENT_D_INO
+ static PyObject *
+ os_DirEntry_inode_impl(DirEntry *self)
+ /*[clinic end generated code: output=156bb3a72162440e
input=3ee7b872ae8649f0]*/
+@@ -15856,6 +15859,7 @@ os_DirEntry_inode_impl(DirEntry *self)
+ return PyLong_FromUnsignedLongLong(self->d_ino);
+ #endif
+ }
++#endif
+
+ static PyObject *
+ DirEntry_repr(DirEntry *self)
+@@ -15892,7 +15896,9 @@ static PyMethodDef DirEntry_methods[] = {
+ OS_DIRENTRY_IS_SYMLINK_METHODDEF
+ OS_DIRENTRY_IS_JUNCTION_METHODDEF
+ OS_DIRENTRY_STAT_METHODDEF
++#ifdef HAVE_DIRENT_D_INO
+ OS_DIRENTRY_INODE_METHODDEF
++#endif
+ OS_DIRENTRY___FSPATH___METHODDEF
+ {"__class_getitem__", Py_GenericAlias,
+ METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
+@@ -16043,7 +16049,10 @@ join_path_filename(const char *path_narrow, const
char* filename, Py_ssize_t fil
+
+ static PyObject *
+ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
+- Py_ssize_t name_len, ino_t d_ino
++ Py_ssize_t name_len
++#ifdef HAVE_DIRENT_D_INO
++ , ino_t d_ino
++#endif
+ #ifdef HAVE_DIRENT_D_TYPE
+ , unsigned char d_type
+ #endif
+@@ -16095,7 +16104,9 @@ DirEntry_from_posix_info(PyObject *module, path_t
*path, const char *name,
+ #ifdef HAVE_DIRENT_D_TYPE
+ entry->d_type = d_type;
+ #endif
++#ifdef HAVE_DIRENT_D_INO
+ entry->d_ino = d_ino;
++#endif
+
+ return (PyObject *)entry;
+
+@@ -16248,7 +16259,10 @@ ScandirIterator_iternext(ScandirIterator *iterator)
+ PyObject *module = PyType_GetModule(Py_TYPE(iterator));
+ entry = DirEntry_from_posix_info(module,
+ &iterator->path, direntp->d_name,
+- name_len, direntp->d_ino
++ name_len
++#ifdef HAVE_DIRENT_D_INO
++ , direntp->d_ino
++#endif
+ #ifdef HAVE_DIRENT_D_TYPE
+ , direntp->d_type
+ #endif
+diff --git a/configure b/configure
+index 6da5e9f3832..c89beb7ef6a 100755
+--- a/configure
++++ b/configure
+@@ -27746,6 +27746,49 @@ then :
+ printf "%s\n" "#define HAVE_DIRENT_D_TYPE 1" >>confdefs.h
+
+
++fi
++
++# check if the dirent structure of a d_ino is defined
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the dirent
structure of a d_ino field" >&5
++printf %s "checking if the dirent structure of a d_ino field... " >&6; }
++if test ${ac_cv_dirent_d_ino+y}
++then :
++ printf %s "(cached) " >&6
++else $as_nop
++
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++
++
++ #include <dirent.h>
++
++ int main(void) {
++ struct dirent entry;
++ return entry.d_ino == 0;
++ }
++
++
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++ ac_cv_dirent_d_ino=yes
++else $as_nop
++ ac_cv_dirent_d_ino=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++ conftest$ac_exeext conftest.$ac_ext
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_dirent_d_ino" >&5
++printf "%s\n" "$ac_cv_dirent_d_ino" >&6; }
++
++if test "x$ac_cv_dirent_d_ino" = xyes
++then :
++
++
++printf "%s\n" "#define HAVE_DIRENT_D_INO 1" >>confdefs.h
++
++
+ fi
+
+ # check if the Linux getrandom() syscall is available
+diff --git a/configure.ac b/configure.ac
+index 80d6738fab5..40f2f950b36 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -7084,6 +7084,11 @@ AS_VAR_IF([ac_cv_dirent_d_type], [yes], [
+ [Define to 1 if the dirent structure has a d_type field])
+ ])
+
++AS_VAR_IF([ac_cv_dirent_d_ino], [yes], [
++ AC_DEFINE([HAVE_DIRENT_D_INO], [1],
++ [Define to 1 if the dirent structure has a d_ino field])
++])
++
+ # check if the Linux getrandom() syscall is available
+ AC_CACHE_CHECK([for the Linux getrandom() syscall],
[ac_cv_getrandom_syscall], [
+ AC_LINK_IFELSE(
+diff --git a/pyconfig.h.in b/pyconfig.h.in
+index 4d8b1d4f254..4a2ba83a872 100644
+--- a/pyconfig.h.in
++++ b/pyconfig.h.in
+@@ -277,6 +277,9 @@
+ /* Define to 1 if the dirent structure has a d_type field */
+ #undef HAVE_DIRENT_D_TYPE
+
++/* Define to 1 if the dirent structure has a d_ino field */
++#undef HAVE_DIRENT_D_INO
++
+ /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+ #undef HAVE_DIRENT_H
+--
+2.46.1
+