diff --git a/interpreters/python/.gitignore b/interpreters/python/.gitignore new file mode 100644 index 00000000000..ad58719cdd4 --- /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 00000000000..44dbe5415d9 --- /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 "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 00000000000..490e08e02f6 --- /dev/null +++ b/interpreters/python/Make.defs @@ -0,0 +1,27 @@ +############################################################################ +# 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),) + +EXTRA_LIBPATHS += -L$(APPDIR)/interpreters/python/install/target +EXTRA_LIBS += -lpython3.13 + +CONFIGURED_APPS += $(APPDIR)/interpreters/python +endif diff --git a/interpreters/python/Makefile b/interpreters/python/Makefile new file mode 100644 index 00000000000..77c959d963a --- /dev/null +++ b/interpreters/python/Makefile @@ -0,0 +1,161 @@ +############################################################################ +# 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 + +$(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 00000000000..beca9d6663a --- /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 00000000000..d806ba564d7 --- /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 00000000000..89a7bc377a5 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 00000000000..dfb9d437a3b --- /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 +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 00000000000..0bf12755af3 --- /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 +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 00000000000..f8e03a2cfc0 --- /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 +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 +--- + 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 00000000000..6d8531ce66d --- /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 +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 +--- + 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 00000000000..cf25d88c2bd --- /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 +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 +--- + 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 00000000000..641233bf4eb --- /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 +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 00000000000..266f704a946 --- /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 +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 00000000000..bb8d3cb43d8 --- /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 +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 00000000000..b52b76be1b2 --- /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 +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 + #endif + ++#ifdef HAVE_SYS_SELECT_H ++#include ++#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 00000000000..d65b1f287c6 --- /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 +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 ++ ++ 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 header file, and it defines `DIR'. + */ + #undef HAVE_DIRENT_H +-- +2.46.1 +