This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 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 526e292c9 interpreters/python: add CMake build support.
526e292c9 is described below

commit 526e292c91d23d5b630a5a69dab7467e2afe0446
Author: raiden00pl <[email protected]>
AuthorDate: Fri Oct 9 19:46:22 2026 +0200

    interpreters/python: add CMake build support.
    
    CPython was only buildable with Make. The CMake build follows the
    Makefile: download and patch CPython, build the host Python, configure
    and build the target libpython, pack the standard library into a ROMFS
    image and link libpython, libHacl_Hash_SHA2 and libexpat into NuttX.
    
    CPython's configure gets the flags NuttX compiles C sources with: the
    directory compile options (the arch toolchain flags, with
    $<COMPILE_LANGUAGE:...> resolved for C), the global NuttX options,
    definitions and include directories. ARFLAGS carries "rcs" because
    CMAKE_AR is the bare archiver.
    
    Tested with qemu-intel64:python and rv-virt:python (with loadable
    modules disabled: CMake has no NSH symbol table for them yet) on QEMU.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: raiden00pl <[email protected]>
---
 interpreters/python/CMakeLists.txt | 397 +++++++++++++++++++++++++++++++++++++
 1 file changed, 397 insertions(+)

diff --git a/interpreters/python/CMakeLists.txt 
b/interpreters/python/CMakeLists.txt
new file mode 100644
index 000000000..c6c9bd724
--- /dev/null
+++ b/interpreters/python/CMakeLists.txt
@@ -0,0 +1,397 @@
+# 
##############################################################################
+# apps/interpreters/python/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+#
+# 
##############################################################################
+
+if(CONFIG_INTERPRETERS_CPYTHON)
+
+  # 
############################################################################
+  # Config and Fetch CPython
+  # 
############################################################################
+
+  set(CPYTHON_VERSION ${CONFIG_INTERPRETERS_CPYTHON_VERSION})
+  string(REGEX MATCH "^[0-9]+\\.[0-9]+" CPYTHON_VERSION_MINOR
+               ${CPYTHON_VERSION})
+  string(REPLACE "." "" CPYTHON_VERSION_NODOT ${CPYTHON_VERSION_MINOR})
+
+  set(CPYTHON_PATH ${CMAKE_CURRENT_LIST_DIR}/Python)
+
+  if(NOT EXISTS ${CPYTHON_PATH})
+    file(GLOB CPYTHON_PATCHES ${CMAKE_CURRENT_LIST_DIR}/patch/*.patch)
+    list(SORT CPYTHON_PATCHES)
+    set(CPYTHON_PATCH_COMMAND)
+    foreach(patch ${CPYTHON_PATCHES})
+      list(
+        APPEND
+        CPYTHON_PATCH_COMMAND
+        COMMAND
+        patch
+        -p1
+        -d
+        ${CPYTHON_PATH}
+        <
+        ${patch})
+    endforeach()
+    list(REMOVE_AT CPYTHON_PATCH_COMMAND 0)
+
+    FetchContent_Declare(
+      cpython_fetch
+      URL https://github.com/python/cpython/archive/v${CPYTHON_VERSION}.zip
+          SOURCE_DIR ${CPYTHON_PATH} BINARY_DIR
+          ${CMAKE_CURRENT_BINARY_DIR}/cpython_fetch
+      PATCH_COMMAND ${CPYTHON_PATCH_COMMAND}
+      DOWNLOAD_NO_PROGRESS true
+      TIMEOUT 120)
+
+    FetchContent_GetProperties(cpython_fetch)
+
+    if(NOT cpython_fetch_POPULATED)
+      FetchContent_Populate(cpython_fetch)
+    endif()
+  endif()
+
+  # 
############################################################################
+  # Build directories
+  # 
############################################################################
+
+  set(BUILDIR ${CMAKE_CURRENT_BINARY_DIR}/build)
+  set(INSTALLDIR ${CMAKE_CURRENT_BINARY_DIR}/install)
+  set(HOSTBUILD ${BUILDIR}/host)
+  set(HOSTINSTALL ${INSTALLDIR}/host)
+  set(HOSTPYTHON ${HOSTINSTALL}/bin/python3)
+  set(TARGETBUILD ${BUILDIR}/target)
+  set(TARGETINSTALL ${INSTALLDIR}/target)
+  set(TARGETMODULES ${TARGETINSTALL}/lib)
+  set(TARGETLIBPYTHON ${TARGETINSTALL}/libpython${CPYTHON_VERSION_MINOR}.a)
+  set(TARGETMODULESPACK ${TARGETBUILD}/lib/python${CPYTHON_VERSION_NODOT}.zip)
+  set(TARGETSTDLIB ${TARGETMODULES}/python${CPYTHON_VERSION_MINOR})
+  set(BUNDLED_WHEELS_DIR ${CPYTHON_PATH}/Lib/ensurepip/_bundled)
+
+  # 
############################################################################
+  # config.site and Setup.local
+  # 
############################################################################
+
+  # The `config.site` file contains settings that override the configuration
+  # settings provided by the `configure` script.  Depending on the features
+  # enabled on NuttX, this file may need to be adjusted.
+
+  set(CONFIG_SITE ${CMAKE_CURRENT_BINARY_DIR}/config.site)
+  file(READ ${CMAKE_CURRENT_LIST_DIR}/config.site.in CONFIG_SITE_CONTENT)
+
+  macro(cpython_config_site var enabled)
+    if(${enabled})
+      string(APPEND CONFIG_SITE_CONTENT "export ${var}=\"yes\"\n")
+    else()
+      string(APPEND CONFIG_SITE_CONTENT "export ${var}=\"no\"\n")
+    endif()
+  endmacro()
+
+  cpython_config_site(ac_cv_func_fork CONFIG_ARCH_HAVE_FORK)
+  cpython_config_site(ac_cv_func_vfork CONFIG_ARCH_HAVE_VFORK)
+  cpython_config_site(ac_cv_func_system CONFIG_SYSTEM_SYSTEM)
+  cpython_config_site(ac_cv_func_getaddrinfo CONFIG_NET)
+  cpython_config_site(ac_cv_func_getnameinfo CONFIG_NET)
+  file(WRITE ${CONFIG_SITE} "${CONFIG_SITE_CONTENT}")
+
+  # The `Setup.local` file disables Python modules: every module listed after
+  # the *disabled* line of `Setup.local.in` is not built.
+
+  set(SETUP_LOCAL ${CMAKE_CURRENT_BINARY_DIR}/Setup.local)
+  file(READ ${CMAKE_CURRENT_LIST_DIR}/Setup.local.in SETUP_LOCAL_CONTENT)
+
+  # _posixsubprocess needs a real fork(): its vfork() support is only an
+  # optimization and the fork() fallback path is compiled unconditionally.
+
+  if(NOT CONFIG_ARCH_HAVE_FORK)
+    string(APPEND SETUP_LOCAL_CONTENT "_posixsubprocess\n")
+  endif()
+  if(NOT CONFIG_LIBC_DLFCN)
+    string(APPEND SETUP_LOCAL_CONTENT "_ctypes\n")
+  endif()
+  if(NOT CONFIG_NET)
+    string(APPEND SETUP_LOCAL_CONTENT "_socket\n")
+  endif()
+  file(WRITE ${SETUP_LOCAL} "${SETUP_LOCAL_CONTENT}")
+
+  # 
############################################################################
+  # Host Python
+  # 
############################################################################
+
+  add_custom_command(
+    OUTPUT ${HOSTPYTHON}
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${HOSTBUILD} ${HOSTINSTALL}
+    COMMAND ${CMAKE_COMMAND} -E chdir ${HOSTBUILD} ${CPYTHON_PATH}/configure
+            --with-pydebug --prefix=${HOSTINSTALL} --disable-test-modules
+    COMMAND make -C ${HOSTBUILD} install
+    COMMENT "CPython: building the host Python"
+    VERBATIM)
+
+  # 
############################################################################
+  # Target Python
+  # 
############################################################################
+
+  # CPython's configure needs the compiler flags NuttX compiles C sources with:
+  # the toolchain flags (add_compile_options() in the arch Toolchain.cmake), 
the
+  # global NuttX options, definitions and include directories.  Generator
+  # expressions in them are evaluated by add_custom_command(), except
+  # $<COMPILE_LANGUAGE:...>, which is resolved here for C.
+
+  get_directory_property(CPYTHON_DIR_OPTIONS COMPILE_OPTIONS)
+  set(CPYTHON_OPTIONS)
+  foreach(opt ${CPYTHON_DIR_OPTIONS})
+    string(REGEX MATCHALL "\\$<COMPILE_LANGUAGE:[^>]*>" langs "${opt}")
+    foreach(lang ${langs})
+      string(REGEX REPLACE "^\\$<COMPILE_LANGUAGE:(.*)>$" "\\1" names 
"${lang}")
+      string(REPLACE "," ";" names "${names}")
+      if("C" IN_LIST names)
+        string(REPLACE "${lang}" "1" opt "${opt}")
+      else()
+        string(REPLACE "${lang}" "0" opt "${opt}")
+      endif()
+    endforeach()
+    list(APPEND CPYTHON_OPTIONS "${opt}")
+  endforeach()
+
+  # Python's configure script requires the optimization flags in OPT
+
+  list(REMOVE_ITEM CPYTHON_OPTIONS -Os)
+
+  set(CPYTHON_NUTTX_DEFINITIONS
+      $<GENEX_EVAL:$<TARGET_PROPERTY:nuttx,NUTTX_DEFINITIONS>>)
+  set(CPYTHON_DEFINITIONS
+      
"$<$<BOOL:${CPYTHON_NUTTX_DEFINITIONS}>:-D$<JOIN:${CPYTHON_NUTTX_DEFINITIONS}, 
-D>>"
+  )
+
+  set(CPYTHON_INCLUDES
+      ${NUTTX_DIR}/include
+      ${NUTTX_BINARY_DIR}/include
+      $<GENEX_EVAL:$<TARGET_PROPERTY:nuttx,NUTTX_INCLUDE_DIRECTORIES>>
+      
$<GENEX_EVAL:$<TARGET_PROPERTY:nuttx_apps_interface,APPS_INCLUDE_DIRECTORIES>>
+      ${CPYTHON_PATH}/Include
+      ${CPYTHON_PATH}/Include/internal
+      ${CMAKE_CURRENT_SOURCE_DIR}/../../system
+      ${CMAKE_CURRENT_SOURCE_DIR}/../../system/zlib/zlib
+      ${TARGETBUILD})
+
+  set(CPYTHON_WARNINGS
+      -Wno-shadow
+      -Wno-undef
+      -Wno-format
+      -Wno-builtin-macro-redefined
+      -Wno-type-limits
+      -Wno-implicit-fallthrough
+      -Wno-char-subscripts
+      -Wno-sign-compare
+      -Wno-unused-const-variable
+      -Wno-unused-function
+      -Wno-unused-variable
+      -Wno-overflow
+      -Wno-unused-but-set-variable
+      -Wno-strict-prototypes
+      -Wno-maybe-uninitialized)
+
+  # CPPFLAGS carries the -D/-U macro flags so preprocessor-only probes
+  # (Misc/platform_triplet.c) do not see the build host's __linux__ when NuttX
+  # is built with the native gcc (x86_64).
+
+  set(CPYTHON_MACRO_OPTIONS ${CPYTHON_OPTIONS})
+  list(FILTER CPYTHON_MACRO_OPTIONS INCLUDE REGEX "^-[DU]")
+
+  set(CPYTHON_CPPFLAGS
+      "$<JOIN:${CPYTHON_MACRO_OPTIONS}, > ${CPYTHON_DEFINITIONS}")
+  set(CPYTHON_CFLAGS
+      "${CMAKE_C_FLAGS} $<JOIN:${CPYTHON_OPTIONS}, > \
+$<JOIN:$<GENEX_EVAL:$<TARGET_PROPERTY:nuttx,NUTTX_COMPILE_OPTIONS>>, > \
+${CPYTHON_DEFINITIONS} -I$<JOIN:${CPYTHON_INCLUDES}, -I> \
+$<JOIN:${CPYTHON_WARNINGS}, > -nostdlib")
+
+  if(CONFIG_NET)
+    set(CPYTHON_CONFIGURE_EXTRAS "")
+  else()
+    set(CPYTHON_CONFIGURE_EXTRAS --disable-ipv6)
+  endif()
+
+  string(REPLACE "-" "" CPYTHON_ARCH "${CONFIG_ARCH}")
+  string(REPLACE "-" "" CPYTHON_ARCH_CHIP "${CONFIG_ARCH_CHIP}")
+
+  execute_process(
+    COMMAND ${CPYTHON_PATH}/config.guess
+    OUTPUT_VARIABLE CPYTHON_BUILD
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+  # CMAKE_AR is the bare archiver (no operation flags), so ARFLAGS carries them
+
+  add_custom_command(
+    OUTPUT ${TARGETBUILD}/Makefile
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${TARGETBUILD}/Modules
+            ${TARGETSTDLIB}
+    COMMAND ${CMAKE_COMMAND} -E copy ${SETUP_LOCAL}
+            ${TARGETBUILD}/Modules/Setup.local
+    COMMAND
+      ${CMAKE_COMMAND} -E env CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
+      AR=${CMAKE_AR} ARFLAGS=rcs "CFLAGS=${CPYTHON_CFLAGS}"
+      "CPPFLAGS=${CPYTHON_CPPFLAGS}" MACHDEP=nuttx OPT=-Os
+      CONFIG_SITE=${CONFIG_SITE} ${CPYTHON_PATH}/configure --disable-shared
+      --prefix=${TARGETINSTALL}
+      --host=${CPYTHON_ARCH}-${CPYTHON_ARCH_CHIP}-nuttx 
--build=${CPYTHON_BUILD}
+      --with-build-python=${HOSTPYTHON} --without-mimalloc --without-pymalloc
+      --disable-test-modules --with-ensurepip=no ${CPYTHON_CONFIGURE_EXTRAS}
+    COMMAND sed -i "s/^#define HAVE_LIBB2 1/\\/* #undef HAVE_LIBB2 *\\//"
+            pyconfig.h
+    COMMAND sed -i "s/-lb2//g" Makefile
+    WORKING_DIRECTORY ${TARGETBUILD}
+    DEPENDS ${HOSTPYTHON} ${CONFIG_SITE} ${SETUP_LOCAL}
+    COMMENT "CPython: configuring the target Python"
+    VERBATIM)
+
+  # Bundled wheels: pip and nuttx-periphery are downloaded with the host system
+  # pip (pip 24.x vendored by the build Python breaks on 3.13) and pre-compiled
+  # with the build Python, which must match the embedded CPython version.
+
+  set(CPYTHON_WHEELS_COMMAND)
+  if(CONFIG_INTERPRETERS_CPYTHON_ENABLE_PIP)
+    list(
+      APPEND
+      CPYTHON_WHEELS_COMMAND
+      COMMAND
+      sh
+      -c
+      "set -e; v=$(${HOSTPYTHON} -c 'import ensurepip; 
print(ensurepip._PIP_VERSION)'); \
+w=${BUNDLED_WHEELS_DIR}/pip-$v-py3-none-any.whl; \
+[ -f $w ] || python3 -m pip download --only-binary=:all: --no-deps --dest 
${BUNDLED_WHEELS_DIR} pip==$v; \
+${HOSTPYTHON} ${CMAKE_CURRENT_LIST_DIR}/repack_wheel_add_pyc.py --package pip 
$w"
+    )
+  endif()
+  if(CONFIG_INTERPRETERS_CPYTHON_INSTALL_NUTTX_PACKAGE)
+    list(
+      APPEND
+      CPYTHON_WHEELS_COMMAND
+      COMMAND
+      sh
+      -c
+      "set -e; w=$(ls ${BUNDLED_WHEELS_DIR}/nuttx_periphery-*-py3-none-any.whl 
2>/dev/null | head -1 || true); \
+if [ -z \"$w\" ]; then python3 -m pip download --only-binary=:all: --no-deps 
--dest ${BUNDLED_WHEELS_DIR} nuttx-periphery; \
+w=$(ls ${BUNDLED_WHEELS_DIR}/nuttx_periphery-*-py3-none-any.whl); fi; \
+${HOSTPYTHON} ${CMAKE_CURRENT_LIST_DIR}/repack_wheel_add_pyc.py --package 
nuttx_periphery $w"
+    )
+  endif()
+
+  # Pre-install the bundled wheels into the target sys.path (zipimport)
+
+  set(CPYTHON_SITE_COMMAND)
+  if(CPYTHON_WHEELS_COMMAND)
+    list(
+      PREPEND
+      CPYTHON_WHEELS_COMMAND
+      COMMAND
+      ${CMAKE_COMMAND}
+      -E
+      make_directory
+      ${BUNDLED_WHEELS_DIR})
+    set(CPYTHON_SITE_PACKAGES ${TARGETSTDLIB}/site-packages)
+    list(
+      APPEND
+      CPYTHON_SITE_COMMAND
+      COMMAND
+      ${CMAKE_COMMAND}
+      -E
+      make_directory
+      ${CPYTHON_SITE_PACKAGES}
+      COMMAND
+      sh
+      -c
+      "set -e; : > ${CPYTHON_SITE_PACKAGES}/bundled_wheels.pth; \
+for w in ${TARGETSTDLIB}/ensurepip/_bundled/*.whl; do [ -f $w ] || continue; \
+echo ../ensurepip/_bundled/$(basename $w) >> 
${CPYTHON_SITE_PACKAGES}/bundled_wheels.pth; done"
+    )
+  endif()
+
+  add_custom_command(
+    OUTPUT ${TARGETLIBPYTHON} ${TARGETBUILD}/Modules/_hacl/libHacl_Hash_SHA2.a
+           ${TARGETBUILD}/Modules/expat/libexpat.a ${CPYTHON_WHEELS_COMMAND}
+    COMMAND make -C ${TARGETBUILD} regen-frozen
+    COMMAND make -C ${TARGETBUILD} libpython${CPYTHON_VERSION_MINOR}.a
+            wasm_stdlib
+    COMMAND
+      ${CMAKE_COMMAND} -E copy
+      ${TARGETBUILD}/libpython${CPYTHON_VERSION_MINOR}.a ${TARGETLIBPYTHON}
+    COMMAND unzip -q -o ${TARGETMODULESPACK} -d ${TARGETSTDLIB}
+            ${CPYTHON_SITE_COMMAND}
+    DEPENDS ${TARGETBUILD}/Makefile
+    COMMENT "CPython: building the target Python"
+    VERBATIM)
+
+  # 
############################################################################
+  # Python modules in ROMFS
+  # 
############################################################################
+
+  set(CPYTHON_ROMFS_IMG ${CMAKE_CURRENT_BINARY_DIR}/romfs_cpython_modules.img)
+  set(CPYTHON_ROMFS_HDR ${CMAKE_CURRENT_BINARY_DIR}/romfs_cpython_modules.h)
+
+  add_custom_command(
+    OUTPUT ${CPYTHON_ROMFS_HDR}
+    COMMAND genromfs -f ${CPYTHON_ROMFS_IMG} -d ${TARGETMODULES} -V 
"ROMFS_Test"
+    COMMAND
+      ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_BINARY_DIR} sh -c
+      "xxd -i romfs_cpython_modules.img | sed -e 's/^unsigned/static const 
unsigned/g' > romfs_cpython_modules.h"
+    DEPENDS ${TARGETLIBPYTHON}
+    COMMENT "CPython: packing the Python modules into ROMFS"
+    VERBATIM)
+
+  add_custom_target(cpython_build DEPENDS ${CPYTHON_ROMFS_HDR})
+
+  # 
############################################################################
+  # Libraries
+  # 
############################################################################
+
+  foreach(lib
+          ${TARGETLIBPYTHON} ${TARGETBUILD}/Modules/_hacl/libHacl_Hash_SHA2.a
+          ${TARGETBUILD}/Modules/expat/libexpat.a)
+    nuttx_add_extra_library(${lib})
+    string(REGEX REPLACE "[^a-zA-Z0-9]" "_" lib_target "${lib}")
+    add_dependencies(${lib_target} cpython_build)
+  endforeach()
+
+  # 
############################################################################
+  # Applications
+  # 
############################################################################
+
+  nuttx_add_application(
+    NAME
+    ${CONFIG_INTERPRETERS_CPYTHON_PROGNAME}
+    SRCS
+    python_wrapper.c
+    STACKSIZE
+    ${CONFIG_INTERPRETERS_CPYTHON_STACKSIZE}
+    PRIORITY
+    ${CONFIG_INTERPRETERS_CPYTHON_PRIORITY}
+    INCLUDE_DIRECTORIES
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CPYTHON_PATH}/Include
+    ${CPYTHON_PATH}/Include/internal
+    ${TARGETBUILD}
+    COMPILE_FLAGS
+    -Wno-shadow
+    -Wno-undef
+    -Wno-strict-prototypes
+    DEPENDS
+    cpython_build)
+
+endif()

Reply via email to