diff --git a/cmake/compiler/gcc/target_xtensa.cmake b/cmake/compiler/gcc/target_xtensa.cmake index 177830427dbdda2..5321204c2df5e74 100644 --- a/cmake/compiler/gcc/target_xtensa.cmake +++ b/cmake/compiler/gcc/target_xtensa.cmake @@ -17,5 +17,4 @@ set(LLEXT_APPEND_FLAGS -fPIC -nostdlib -nodefaultlibs - -shared ) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 4e8f454711bf990..86834d6b225b49c 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -5099,6 +5099,12 @@ endmacro() # loadable extensions (llexts). # +# Usage: +# add_llext_target( +# OUTPUT +# SOURCES +# ) +# # 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 @@ -5142,15 +5148,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 +5165,84 @@ function(add_llext_target target_name) "$" ) - # 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 $) + + elseif(CONFIG_XTENSA) + + # Ensure shared library support is enabled + set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS true) + + # Create a shared library + add_library(${llext_lib_target} SHARED ${source_file}) + set(llext_lib_output $) + + # 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_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_include_directories(${target_name}_lib SYSTEM PUBLIC + target_include_directories(${llext_lib_target} SYSTEM PUBLIC $ ) - 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 $ ${output_file} - DEPENDS ${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} - $ + OUTPUT ${llext_pkg_output} COMMAND $ $ $.xt.* - $${pre_output_file} - $${output_file} + $${llext_lib_output} + $${llext_pkg_output} $ - DEPENDS ${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 + get_filename_component(output_name ${llext_pkg_output} NAME) + add_custom_target(${target_name} + COMMENT "Generating ${output_name}" + DEPENDS ${llext_pkg_output} + ) endfunction()