Rework post-build to support multiple executables

When building greentea tests, each test is an executable with its
own output binary path. This is also the case when a user project
produces multiple executables. But the current implementation of
post-build operations always assumes there's only one executable,
at the root of the build directory.

The post-build command depends on Mbed target, and it always takes
the the executable we build as an input file. To achieve this, we
let each Mbed target (that has a post-build command) define a function

    function(mbed_post_build_function target)

which takes a CMake executable target as an argument from which it can
get its binary path using generator expressions. It generates and adds
to the passed executable target a post-build custom command.

Notes:
* The function name needs to be exact, because CMake only supports
literal function calls - CMake can't dereference a function name from
a variable. To avoid multiple definitions of this function, each Mbed
target needs to guard it with a macro to check if the user is
building this Mbed target.
* `mbed_post_build_function()` is a function, but it is usually
defined by another macro rather than a parent function, because
nesting functions would make many variables inaccessible inside the
innermost `mbed_post_build_function()`.
* There's no more need to force regenerate images. Previously, post-
build commands were custom *targets* which always got to run, so we
force regenerated images on every build to avoid patching an image
that's already been patched once on previous build. Now post-build
commands are custom *commands* of the same executable target, and they
are only run if the executable target itself is rebuilt.
pull/14953/head
Lingkai Dong 2021-07-19 14:34:59 +01:00
parent fcd57b24d3
commit 351680fb18
6 changed files with 131 additions and 134 deletions

View File

@ -144,12 +144,16 @@ target_include_directories(mbed-core
add_library(mbed-device_key INTERFACE) add_library(mbed-device_key INTERFACE)
add_library(mbed-rtos INTERFACE) add_library(mbed-rtos INTERFACE)
# Include targets/ first, because any post-build hook needs to be defined
# before other parts of Mbed OS can add greentea tests which require
# mbed_set_post_build().
add_subdirectory(targets)
add_subdirectory(cmsis) add_subdirectory(cmsis)
add_subdirectory(drivers) add_subdirectory(drivers)
add_subdirectory(hal) add_subdirectory(hal)
add_subdirectory(platform) add_subdirectory(platform)
add_subdirectory(rtos) add_subdirectory(rtos)
add_subdirectory(targets)
add_subdirectory(storage) add_subdirectory(storage)
add_subdirectory(events) add_subdirectory(events)
add_subdirectory(connectivity) add_subdirectory(connectivity)

View File

@ -3,28 +3,30 @@
include(mbed_set_post_build) include(mbed_set_post_build)
set(MBED_POST_BUILD_TFM_DIR "${CMAKE_CURRENT_LIST_DIR}")
# #
# Sign TF-M secure and non-secure images and combine them with the bootloader # Sign TF-M secure and non-secure images and combine them with the bootloader
# #
function(mbed_post_build_tfm_sign_image macro(mbed_post_build_tfm_sign_image
mbed_target mbed_tfm_target
tfm_target tfm_target
target_path target_path
secure_bin secure_bin
) )
find_package(Python3) if("${mbed_tfm_target}" STREQUAL "${MBED_TARGET}")
function(mbed_post_build_function target)
set(mbed_target_name ${mbed_target}) find_package(Python3)
set(post_build_command add_custom_command(
COMMAND ${Python3_EXECUTABLE} TARGET
${MBED_POST_BUILD_TFM_DIR}/generate_mbed_image.py ${target}
--tfm-target ${tfm_target} POST_BUILD
--target-path ${target_path} COMMAND
--secure-bin ${secure_bin} ${Python3_EXECUTABLE}
--non-secure-bin ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.bin ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/generate_mbed_image.py
) --tfm-target ${tfm_target}
--target-path ${target_path}
mbed_set_post_build_operation() --secure-bin ${secure_bin}
endfunction() --non-secure-bin $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.bin
)
endfunction()
endif()
endmacro()

View File

@ -3,72 +3,90 @@
include(mbed_set_post_build) include(mbed_set_post_build)
set(MBED_POST_BUILD_CYPRESS_DIR "${CMAKE_CURRENT_LIST_DIR}")
# #
# Merge Cortex-M4 HEX and a Cortex-M0 HEX. # Merge Cortex-M4 HEX and a Cortex-M0 HEX.
# #
function(mbed_post_build_psoc6_merge_hex mbed_target_name) macro(mbed_post_build_psoc6_merge_hex cypress_psoc6_target)
find_package(Python3) if("${cypress_psoc6_target}" STREQUAL "${MBED_TARGET}")
function(mbed_post_build_function target)
find_package(Python3)
# Copy ${ARGN} to a variable first as it cannot be used directly with # Copy ${ARGN} to a variable first as it cannot be used directly with
# the list() command # the list() command
set (extra_macro_args ${ARGN}) set (extra_macro_args ${ARGN})
# Get the number of arguments past the last expected argument # Get the number of arguments past the last expected argument
list(LENGTH extra_macro_args num_extra_args) list(LENGTH extra_macro_args num_extra_args)
if(${num_extra_args} GREATER 0) if(${num_extra_args} GREATER 0)
# Get extra argument as `cortex_m0_hex` # Get extra argument as `cortex_m0_hex`
list(GET extra_macro_args 0 cortex_m0_hex) list(GET extra_macro_args 0 cortex_m0_hex)
set(post_build_command set(post_build_command
COMMAND ${Python3_EXECUTABLE} ${MBED_POST_BUILD_CYPRESS_DIR}/PSOC6.py ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PSOC6.py
merge merge
--elf ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.elf --elf $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.elf
--m4hex ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.hex --m4hex $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.hex
--m0hex ${cortex_m0_hex} --m0hex ${cortex_m0_hex}
) )
else() else()
set(post_build_command set(post_build_command
COMMAND ${Python3_EXECUTABLE} ${MBED_POST_BUILD_CYPRESS_DIR}/PSOC6.py ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PSOC6.py
merge merge
--elf ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.elf --elf $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.elf
--m4hex ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.hex --m4hex $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.hex
) )
endif()
add_custom_command(
TARGET
${target}
POST_BUILD
COMMAND
${post_build_command}
)
endfunction()
endif() endif()
endmacro()
mbed_set_post_build_operation()
endfunction()
# #
# Sign a Cortex-M4 HEX with Cortex-M0 HEX. # Sign a Cortex-M4 HEX with Cortex-M0 HEX.
# #
function(mbed_post_build_psoc6_sign_image macro(mbed_post_build_psoc6_sign_image
m0hex_filename m0hex_filename
mbed_target_name cypress_psoc6_target
policy_file_name policy_file_name
boot_scheme boot_scheme
cm0_img_id cm0_img_id
cm4_img_id cm4_img_id
cortex_m0_hex cortex_m0_hex
) )
find_package(Python3) if("${cypress_psoc6_target}" STREQUAL "${MBED_TARGET}")
function(mbed_post_build_function target)
find_package(Python3)
set(post_build_command set(post_build_command
COMMAND ${Python3_EXECUTABLE} ${MBED_POST_BUILD_CYPRESS_DIR}/PSOC6.py ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PSOC6.py
sign sign
--build-dir ${CMAKE_BINARY_DIR} --build-dir ${CMAKE_BINARY_DIR}
--m0hex-filename ${m0hex_filename} --m0hex-filename ${m0hex_filename}
--target-name ${mbed_target_name} --target-name ${cypress_psoc6_target}
--policy-file-name ${policy_file_name} --policy-file-name ${policy_file_name}
--boot-scheme ${boot_scheme} --boot-scheme ${boot_scheme}
--cm0-img-id ${cm0_img_id} --cm0-img-id ${cm0_img_id}
--cm4-img-id ${cm4_img_id} --cm4-img-id ${cm4_img_id}
--elf ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.elf --elf $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.elf
--m4hex ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.hex --m4hex $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.hex
--m0hex ${cortex_m0_hex} --m0hex ${cortex_m0_hex}
) )
mbed_set_post_build_operation() add_custom_command(
endfunction() TARGET
${target}
POST_BUILD
COMMAND
${post_build_command}
)
endfunction()
endif()
endmacro()

View File

@ -6,22 +6,27 @@ include(${MBED_PATH}/tools/cmake/mbed_set_post_build.cmake)
# #
# Sign TF-M secure and non-secure images and combine them with the bootloader # Sign TF-M secure and non-secure images and combine them with the bootloader
# #
function(mbed_post_build_nuvoton_tfm_sign_image_tgt macro(mbed_post_build_nuvoton_tfm_sign_image_tgt
mbed_target nuvoton_target
tfm_import_path tfm_import_path
signing_key signing_key
) )
find_package(Python3) if("${nuvoton_target}" STREQUAL "${MBED_TARGET}")
function(mbed_post_build_function target)
find_package(Python3)
set(mbed_target_name ${mbed_target}) add_custom_command(
set(post_build_command TARGET
COMMAND ${Python3_EXECUTABLE} ${target}
${MBED_PATH}/targets/TARGET_NUVOTON/scripts/NUVOTON.py POST_BUILD
tfm_sign_image_tgt COMMAND
--tfm-import-path ${tfm_import_path} ${Python3_EXECUTABLE}
--signing_key ${signing_key} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/NUVOTON.py
--non-secure-bin ${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.bin tfm_sign_image_tgt
) --tfm-import-path ${tfm_import_path}
--signing_key ${signing_key}
mbed_set_post_build_operation() --non-secure-bin $<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.bin
endfunction() )
endfunction()
endif()
endmacro()

View File

@ -3,18 +3,21 @@
include(mbed_set_post_build) include(mbed_set_post_build)
set(MBED_POST_BUILD_NXP_DIR "${CMAKE_CURRENT_LIST_DIR}")
# #
# Patch an LPC target vector table in the binary file. # Patch an LPC target vector table in the binary file.
# #
function(mbed_post_build_lpc_patch_vtable mbed_target_name) macro(mbed_post_build_lpc_patch_vtable nxp_lpc_target)
find_package(Python3) if("${nxp_lpc_target}" STREQUAL "${MBED_TARGET}")
function(mbed_post_build_function target)
set(post_build_command find_package(Python3)
COMMAND ${Python3_EXECUTABLE} ${MBED_POST_BUILD_NXP_DIR}/LPC.py add_custom_command(
${CMAKE_BINARY_DIR}/$<TARGET_PROPERTY:mbed-post-build-bin-${mbed_target_name},application>.bin TARGET
) ${target}
POST_BUILD
mbed_set_post_build_operation() COMMAND
endfunction() ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/LPC.py
$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.bin
)
endfunction()
endif()
endmacro()

View File

@ -39,33 +39,12 @@ function(mbed_generate_bin_hex target)
TARGET TARGET
${target} ${target}
POST_BUILD POST_BUILD
COMMAND
${CMAKE_POST_BUILD_COMMAND} ${CMAKE_POST_BUILD_COMMAND}
COMMENT COMMENT
"executable:" "executable:"
VERBATIM VERBATIM
) )
if(TARGET mbed-post-build-bin-${MBED_TARGET})
# Remove the .elf file to force regenerate the application binaries
# (including .bin and .hex). This ensures that the post-build script runs
# on a raw application instead of a previous build that already went
# through the post-build process once.
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${target}.elf)
# Pass the application's name to the Mbed target's post build operation
set_target_properties(mbed-post-build-bin-${MBED_TARGET}
PROPERTIES
application ${target}
)
# The artefacts must be created before they can be further manipulated
add_dependencies(mbed-post-build-bin-${MBED_TARGET} ${target})
# Add a post-build hook to the top-level CMake target in the form of a
# CMake custom target. The hook depends on Mbed target specific
# post-build CMake target which has a custom command attached to it.
add_custom_target(mbed-post-build ALL DEPENDS mbed-post-build-bin-${MBED_TARGET})
endif()
endfunction() endfunction()
# #
@ -112,25 +91,11 @@ function(mbed_set_post_build target)
mbed_validate_application_profile(${target}) mbed_validate_application_profile(${target})
mbed_generate_bin_hex(${target}) mbed_generate_bin_hex(${target})
if(COMMAND mbed_post_build_function)
mbed_post_build_function(${target})
endif()
if(HAVE_MEMAP_DEPS) if(HAVE_MEMAP_DEPS)
mbed_generate_map_file(${target}) mbed_generate_map_file(${target})
endif() endif()
endfunction() endfunction()
#
# Sets the post build operation for Mbed targets.
#
macro(mbed_set_post_build_operation)
add_custom_target(mbed-post-build-bin-${mbed_target_name})
add_custom_command(
TARGET
mbed-post-build-bin-${mbed_target_name}
POST_BUILD
COMMAND
${post_build_command}
VERBATIM
)
endmacro()