diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d1d45ef0e..aef5509bd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,7 +184,6 @@ endfunction() # Parse toolchain generated map file of `target` and display a readable table format. # function(mbed_generate_map_file target) - find_package (Python3) add_custom_command( TARGET ${target} @@ -220,7 +219,10 @@ endfunction() function(mbed_set_post_build target) mbed_validate_application_profile(${target}) mbed_generate_bin_hex(${target}) - mbed_generate_map_file(${target}) + + if(HAVE_MEMAP_DEPS) + mbed_generate_map_file(${target}) + endif() endfunction() # Ninja requires to be forced for response files diff --git a/tools/cmake/CheckPythonPackage.cmake b/tools/cmake/CheckPythonPackage.cmake new file mode 100644 index 0000000000..9a886dc608 --- /dev/null +++ b/tools/cmake/CheckPythonPackage.cmake @@ -0,0 +1,62 @@ +# Copyright (c) 2020 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# CMake functions for checking for Python packages +# Requires PYTHON_EXECUTABLE to be defined. Call FindPython first! + +# set OUTPUT_VAR to whether PACKAGENAME was found +function(check_python_package PACKAGENAME OUTPUT_VAR) + # can't have Python packages without Python! + if(NOT Python3_FOUND) + set(${OUTPUT_VAR} FALSE PARENT_SCOPE) + return() + endif() + + set(NEED_TO_RUN_CHECK TRUE) + + if(DEFINED ${OUTPUT_VAR}) + if(${OUTPUT_VAR}) + # if the python interpreter changed, we need to recheck + if("${PY_INTERP_FOR_${OUTPUT_VAR}}" STREQUAL "${Python3_EXECUTABLE}") + set(NEED_TO_RUN_CHECK FALSE) + endif() + endif() + endif() + + if(NEED_TO_RUN_CHECK) + set(PY_INTERP_FOR_${OUTPUT_VAR} ${Python3_EXECUTABLE} CACHE INTERNAL "The python interpreter used to run the ${OUTPUT_VAR} check" FORCE) + + execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import ${PACKAGENAME}" RESULT_VARIABLE PACKAGECHECK_RESULT + ) + + if(${PACKAGECHECK_RESULT} EQUAL 0) + set(HAVE_PACKAGE TRUE) + else() + set(HAVE_PACKAGE FALSE) + endif() + + if(HAVE_PACKAGE) + message(STATUS "Checking for Python package ${PACKAGENAME} -- found") + else() + message(STATUS "Checking for Python package ${PACKAGENAME} -- not found") + endif() + + set(${OUTPUT_VAR} ${HAVE_PACKAGE} CACHE BOOL "Whether the Python package ${PACKAGENAME} was found" FORCE) + mark_as_advanced(${OUTPUT_VAR}) + endif() +endfunction(check_python_package) + +# check that PACKAGENAME can be imported, and print an error if not +function(verify_python_package PACKAGENAME) + + # we can just generate our own variable name + string(TOUPPER "HAVE_${PACKAGENAME}" HAVE_VAR_NAME) + + check_python_package(${PACKAGENAME} ${HAVE_VAR_NAME}) + + if(NOT ${HAVE_VAR_NAME}) + message(FATAL_ERROR "The required Python package ${PACKAGENAME} was not found in ${Python3_EXECUTABLE}. Please install it.") + endif() + +endfunction(verify_python_package) diff --git a/tools/cmake/app.cmake b/tools/cmake/app.cmake index 492252235e..8d7318c1d0 100644 --- a/tools/cmake/app.cmake +++ b/tools/cmake/app.cmake @@ -23,3 +23,35 @@ enable_language(C CXX ASM) # set executable suffix (has to be done after enabling languages) # Note: This is nice to have, but is also required because STM32Cube will only work on files with a .elf extension set(CMAKE_EXECUTABLE_SUFFIX .elf) + +# Find Python +find_package(Python3 COMPONENTS Interpreter) +include(${CMAKE_CURRENT_LIST_DIR}/CheckPythonPackage.cmake) + +# Check python packages from requirements.txt +file(STRINGS ${CMAKE_CURRENT_LIST_DIR}/requirements.txt PYTHON_REQUIREMENTS) +foreach(REQUIREMENT ${PYTHON_REQUIREMENTS}) + # Look for a string from the start of each line that does not contain "<", ">", "=", or " ". + if(REQUIREMENT MATCHES "^([^<>= ]+)") + set(PACKAGE_NAME ${CMAKE_MATCH_1}) + 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() + else() + message(FATAL_ERROR "Cannot parse line \"${REQUIREMENT}\" in requirements.txt") + 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 (python3, intelhex, prettytable) so the memory map cannot be printed") +endif() + diff --git a/tools/cmake/requirements.txt b/tools/cmake/requirements.txt index 5d7a71bdbb..fce949fecb 100644 --- a/tools/cmake/requirements.txt +++ b/tools/cmake/requirements.txt @@ -1,3 +1,4 @@ prettytable==0.7.2 future==0.16.0 Jinja2>=2.10.1,<2.11 +intelhex>=2.3.0,<3.0.0