mbed-os/tools/cmake/mbed_python_interpreter.cmake

97 lines
3.8 KiB
CMake

# Copyright (c) 2024 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# CMake script to find the Python interpreter and either install or find
# Mbed's dependencies.
option(MBED_CREATE_PYTHON_VENV "If true, Mbed OS will create its own virtual environment (venv) and install its Python packages there. This removes the need to manually install Python packages." TRUE)
if(MBED_CREATE_PYTHON_VENV)
# Use the venv.
# Note: venv is stored in the source directory as it can be shared between all the build directories
# (not target specific)
set(MBED_VENV_LOCATION ${MBED_SOURCE_DIR}/venv)
set(VENV_STAMP_FILE ${MBED_VENV_LOCATION}/mbed-venv.stamp)
set(MBED_REQUIREMENTS_TXT_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../requirements.txt")
# Find Python3, using the venv if it already exists
set (ENV{VIRTUAL_ENV} ${MBED_VENV_LOCATION})
set (Python3_FIND_VIRTUALENV FIRST)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
include(CheckPythonPackage)
set(NEED_TO_CREATE_VENV FALSE)
set(NEED_TO_INSTALL_PACKAGES FALSE)
if(NOT EXISTS "${VENV_STAMP_FILE}")
set(NEED_TO_CREATE_VENV TRUE)
set(NEED_TO_INSTALL_PACKAGES TRUE)
elseif("${MBED_REQUIREMENTS_TXT_LOCATION}" IS_NEWER_THAN "${VENV_STAMP_FILE}")
set(NEED_TO_INSTALL_PACKAGES TRUE)
endif()
if(NEED_TO_CREATE_VENV)
# Create venv.
# Using approach from here: https://discourse.cmake.org/t/possible-to-create-a-python-virtual-env-from-cmake-and-then-find-it-with-findpython3/1132/2
message(STATUS "Mbed: Creating virtual environment with Python interpreter ${Python3_EXECUTABLE}")
execute_process(
COMMAND ${Python3_EXECUTABLE} -m venv ${MBED_VENV_LOCATION}
COMMAND_ERROR_IS_FATAL ANY
)
## Reset FindPython3 cache variables so it will run again
unset(Python3_EXECUTABLE)
unset(_Python3_EXECUTABLE CACHE)
unset(_Python3_INTERPRETER_PROPERTIES CACHE)
unset(_Python3_INTERPRETER_SIGNATURE CACHE)
## Launch a new search for Python3
find_package (Python3 REQUIRED COMPONENTS Interpreter)
endif()
if(NEED_TO_INSTALL_PACKAGES)
message(STATUS "Mbed: Installing Python requirements for Mbed into venv")
# Upgrade pip first in case it needs an upgrade, to prevent a warning being printed
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install --upgrade pip
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install -r ${MBED_REQUIREMENTS_TXT_LOCATION}
COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "Mbed: venv created successfully")
file(TOUCH ${VENV_STAMP_FILE})
endif()
# We always have the memap deps with the venv
set(HAVE_MEMAP_DEPS TRUE)
else()
find_package(Python3 REQUIRED COMPONENTS Interpreter)
include(CheckPythonPackage)
# Check python packages
set(PYTHON_PACKAGES_TO_CHECK intelhex prettytable future jinja2)
foreach(PACKAGE_NAME ${PYTHON_PACKAGES_TO_CHECK})
string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UCASE) # Ucase name needed for CMake variable
string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LCASE) # Lcase name needed for import statement
check_python_package(${PACKAGE_NAME_LCASE} HAVE_PYTHON_${PACKAGE_NAME_UCASE})
if(NOT HAVE_PYTHON_${PACKAGE_NAME_UCASE})
message(WARNING "Missing Python dependency ${PACKAGE_NAME}")
endif()
endforeach()
# Check deps for memap
if(Python3_FOUND AND HAVE_PYTHON_INTELHEX AND HAVE_PYTHON_PRETTYTABLE)
set(HAVE_MEMAP_DEPS TRUE)
else()
set(HAVE_MEMAP_DEPS FALSE)
message(STATUS "Missing Python dependencies (at least one of: python3, intelhex, prettytable) so the memory map cannot be printed")
endif()
endif()