Use a virtual environment for Python packages by default (#261)

* Use a virtual environment for Python packages by default

* Install python3-venv in CI

* Don't use sudo

* Oops missed a "STATUS"

* Fix second build dir not using venv
pull/15510/head
Jamie Smith 2024-03-14 10:13:23 -07:00 committed by GitHub
parent b2193029c2
commit 862f46233c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 115 additions and 30 deletions

View File

@ -214,10 +214,10 @@ jobs:
name: Checkout repo
uses: actions/checkout@v3
- name: Install Python packages
- name: Install python3-venv
run: |
python3 -m pip install -r tools/requirements.txt
apt-get update
apt-get install -y python3-venv
-
name: cmake build

View File

@ -10,9 +10,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Install Python packages
- name: Install python3-venv
run: |
python3 -m pip install -r tools/requirements.txt
apt-get update
apt-get install -y python3-venv
- name: Build NUCLEO_G031K8 with baremetal profile
run: |

View File

@ -9,17 +9,19 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Python packages
run: |
python3 -m pip install -r tools/requirements.txt
python3 -m pip install -r tools/requirements.txt
# Note: For this CI job we use MBED_CREATE_PYTHON_VENV=FALSE so that we can make sure
# this mode works.
- name: Build the multiple_executables example
run: |
cd tools/cmake/tests/multiple_executables/
mkdir cmake_build
cd cmake_build
cmake -DMBED_TARGET=ARM_MUSCA_S1 ..
cmake -DMBED_TARGET=ARM_MUSCA_S1 -DMBED_CREATE_PYTHON_VENV=FALSE ..
cmake --build .
- name: Verify the post-build command has run successfully on each image

View File

@ -11,28 +11,7 @@ if(CCACHE)
endif()
# Find Python (needed to generate configurations)
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()
include(mbed_python_interpreter)
include(mbed_generate_config_header)
include(mbed_target_functions)

View File

@ -32,6 +32,12 @@ set(MBED_INTERNAL_LAST_MBED_TARGET "${MBED_TARGET}" CACHE INTERNAL "Previous mbe
get_filename_component(MBED_APP_JSON_PATH "${MBED_APP_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR})
get_filename_component(CUSTOM_TARGETS_JSON_PATH "${CUSTOM_TARGETS_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR})
# Make it so that if mbed_app.json or custom_targets.json are modified, CMake is rerun.
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MBED_APP_JSON_PATH})
if(EXISTS "${CUSTOM_TARGETS_JSON_PATH}" AND (NOT IS_DIRECTORY "${CUSTOM_TARGETS_JSON_PATH}"))
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CUSTOM_TARGETS_JSON_PATH})
endif()
# Check if mbed_app.json was modified
# Note: if the path is an empty string, get_filename_component(ABSOLUTE) will convert it to a directory,
# so we have to verify that the path we have is a file, not a dir.
@ -92,6 +98,7 @@ if(MBED_NEED_TO_RECONFIGURE)
set(MBEDTOOLS_CONFIGURE_COMMAND ${Python3_EXECUTABLE}
-c "import mbed_tools.cli.main\; exit(mbed_tools.cli.main.cli())" # This is used instead of invoking mbed_tools as a script, because it might not be on the user's PATH.
-v # without -v, warnings (e.g. "you have tried to override a nonexistent parameter") do not get printed
configure
-t GCC_ARM # GCC_ARM is currently the only supported toolchain
-m "${MBED_TARGET}"

View File

@ -0,0 +1,96 @@
# 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 ${CMAKE_SOURCE_DIR}/mbed-os/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()