llext: use CMake shared library support on Xtensa
This change reworks the Xtensa support in llext to use CMake's native shared library support, instead of manually running "gcc -shared". This change minimizes the differences in llext handling by defining appropriate CMake targets for the different architectures. Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This commit is contained in:
parent
f61b003b07
commit
1e47c64266
|
@ -17,5 +17,4 @@ set(LLEXT_APPEND_FLAGS
|
|||
-fPIC
|
||||
-nostdlib
|
||||
-nodefaultlibs
|
||||
-shared
|
||||
)
|
||||
|
|
|
@ -5099,6 +5099,12 @@ endmacro()
|
|||
# loadable extensions (llexts).
|
||||
#
|
||||
|
||||
# Usage:
|
||||
# add_llext_target(<target_name>
|
||||
# OUTPUT <output_file>
|
||||
# SOURCES <source_file>
|
||||
# )
|
||||
#
|
||||
# Add a custom target that compiles a single source file to a .llext file.
|
||||
#
|
||||
# Output and source files must be specified using the OUTPUT and SOURCES
|
||||
|
@ -5112,6 +5118,14 @@ endmacro()
|
|||
# The C_FLAGS argument can be used to pass additional compiler flags to the
|
||||
# compilation of this particular llext.
|
||||
#
|
||||
# The following custom properties of <target_name> are defined and can be
|
||||
# retrieved using the get_target_property() function:
|
||||
#
|
||||
# - lib_target Target name for the source compilation and/or link step.
|
||||
# - lib_output The binary file resulting from compilation and/or
|
||||
# linking steps.
|
||||
# - pkg_output The final .llext file.
|
||||
#
|
||||
# Example usage:
|
||||
# add_llext_target(hello_world
|
||||
# OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
|
||||
|
@ -5131,10 +5145,8 @@ function(add_llext_target target_name)
|
|||
message(FATAL_ERROR "add_llext_target: CONFIG_LLEXT must be enabled")
|
||||
endif()
|
||||
|
||||
# Output file must be provided
|
||||
if(NOT LLEXT_OUTPUT)
|
||||
message(FATAL_ERROR "add_llext_target: OUTPUT argument must be provided")
|
||||
endif()
|
||||
# Source and output files must be provided
|
||||
zephyr_check_arguments_required_all("add_llext_target" LLEXT OUTPUT SOURCES)
|
||||
|
||||
# Source list length must currently be 1
|
||||
list(LENGTH LLEXT_SOURCES source_count)
|
||||
|
@ -5142,15 +5154,8 @@ function(add_llext_target target_name)
|
|||
message(FATAL_ERROR "add_llext_target: only one source file is supported")
|
||||
endif()
|
||||
|
||||
set(output_file ${LLEXT_OUTPUT})
|
||||
set(llext_pkg_output ${LLEXT_OUTPUT})
|
||||
set(source_file ${LLEXT_SOURCES})
|
||||
get_filename_component(output_name ${output_file} NAME)
|
||||
|
||||
# Add user-visible target and dependency
|
||||
add_custom_target(${target_name}
|
||||
COMMENT "Compiling ${output_name}"
|
||||
DEPENDS ${output_file}
|
||||
)
|
||||
|
||||
# Convert the LLEXT_REMOVE_FLAGS list to a regular expression, and use it to
|
||||
# filter out these flags from the Zephyr target settings
|
||||
|
@ -5166,62 +5171,86 @@ function(add_llext_target target_name)
|
|||
"$<FILTER:${zephyr_flags},EXCLUDE,${llext_remove_flags_regexp}>"
|
||||
)
|
||||
|
||||
# Compile the source file to an object file using current Zephyr settings
|
||||
# but a different set of flags
|
||||
add_library(${target_name}_lib OBJECT ${source_file})
|
||||
target_compile_definitions(${target_name}_lib PRIVATE
|
||||
# Compile the source file using current Zephyr settings but a different
|
||||
# set of flags.
|
||||
# This is currently arch-specific since the ARM loader for .llext files
|
||||
# expects object file format, while the Xtensa one uses shared libraries.
|
||||
set(llext_lib_target ${target_name}_llext_lib)
|
||||
if(CONFIG_ARM)
|
||||
|
||||
# Create an object library to compile the source file
|
||||
add_library(${llext_lib_target} OBJECT ${source_file})
|
||||
set(llext_lib_output $<TARGET_OBJECTS:${llext_lib_target}>)
|
||||
|
||||
elseif(CONFIG_XTENSA)
|
||||
|
||||
# Create a shared library
|
||||
add_library(${llext_lib_target} SHARED ${source_file})
|
||||
set(llext_lib_output $<TARGET_FILE:${llext_lib_target}>)
|
||||
|
||||
# Add the llext flags to the linking step as well
|
||||
target_link_options(${llext_lib_target} PRIVATE
|
||||
${LLEXT_APPEND_FLAGS}
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${llext_lib_target} PRIVATE
|
||||
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_compile_options(${target_name}_lib PRIVATE
|
||||
target_compile_options(${llext_lib_target} PRIVATE
|
||||
${zephyr_filtered_flags}
|
||||
${LLEXT_APPEND_FLAGS}
|
||||
${LLEXT_C_FLAGS}
|
||||
)
|
||||
target_include_directories(${target_name}_lib PRIVATE
|
||||
target_include_directories(${llext_lib_target} PRIVATE
|
||||
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_include_directories(${target_name}_lib SYSTEM PUBLIC
|
||||
target_include_directories(${llext_lib_target} SYSTEM PUBLIC
|
||||
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
add_dependencies(${target_name}_lib
|
||||
add_dependencies(${llext_lib_target}
|
||||
zephyr_interface
|
||||
zephyr_generated_headers
|
||||
)
|
||||
|
||||
# Arch-specific conversion of the object file to an llext
|
||||
# Arch-specific packaging of the built binary file into an .llext file
|
||||
if(CONFIG_ARM)
|
||||
|
||||
# No conversion required, simply copy the object file
|
||||
# No packaging required, simply copy the object file
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:${target_name}_lib> ${output_file}
|
||||
DEPENDS ${target_name}_lib $<TARGET_OBJECTS:${target_name}_lib>
|
||||
OUTPUT ${llext_pkg_output}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${llext_lib_output} ${llext_pkg_output}
|
||||
DEPENDS ${llext_lib_target} ${llext_lib_output}
|
||||
)
|
||||
|
||||
elseif(CONFIG_XTENSA)
|
||||
|
||||
# Generate an intermediate file name
|
||||
get_filename_component(output_dir ${output_file} DIRECTORY)
|
||||
get_filename_component(output_name_we ${output_file} NAME_WE)
|
||||
set(pre_output_file ${output_dir}/${output_name_we}.pre.llext)
|
||||
|
||||
# Need to convert the object file to a shared library, then strip some sections
|
||||
# Need to strip the shared library of some sections
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
BYPRODUCTS ${pre_output_file}
|
||||
COMMAND ${CMAKE_C_COMPILER} ${LLEXT_APPEND_FLAGS}
|
||||
-o ${pre_output_file}
|
||||
$<TARGET_OBJECTS:${target_name}_lib>
|
||||
OUTPUT ${llext_pkg_output}
|
||||
COMMAND $<TARGET_PROPERTY:bintools,strip_command>
|
||||
$<TARGET_PROPERTY:bintools,strip_flag>
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_remove_section>.xt.*
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_infile>${pre_output_file}
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_outfile>${output_file}
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_infile>${llext_lib_output}
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_outfile>${llext_pkg_output}
|
||||
$<TARGET_PROPERTY:bintools,strip_flag_final>
|
||||
DEPENDS ${target_name}_lib $<TARGET_OBJECTS:${target_name}_lib>
|
||||
DEPENDS ${llext_lib_target} ${llext_lib_output}
|
||||
)
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "add_llext_target: unsupported architecture")
|
||||
endif()
|
||||
|
||||
# Add user-visible target and dependency, and fill in properties
|
||||
get_filename_component(output_name ${llext_pkg_output} NAME)
|
||||
add_custom_target(${target_name}
|
||||
COMMENT "Generating ${output_name}"
|
||||
DEPENDS ${llext_pkg_output}
|
||||
)
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
lib_target ${llext_lib_target}
|
||||
lib_output ${llext_lib_output}
|
||||
pkg_output ${llext_pkg_output}
|
||||
)
|
||||
endfunction()
|
||||
|
|
Loading…
Reference in a new issue