Skip to content

Commit

Permalink
llext: define add_llext_target() for llext compilation
Browse files Browse the repository at this point in the history
This patch defines a generic function that encapsulates all the
architecture-specific machinery needed to compile llexts from source
files. Current tests are updated to use this function.

Output and source files must be specified using the OUTPUT and SOURCES
arguments. Only one source file is currently supported.

Arch-specific flags will be added automatically. The C_FLAGS argument
can be used to pass additional compiler flags to the compilation of
the source file.

Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
  • Loading branch information
pillo79 committed Jan 17, 2024
1 parent 2b30259 commit 12cdb55
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 27 deletions.
86 changes: 86 additions & 0 deletions cmake/modules/llext.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (c) 2024 Arduino SA

include_guard(GLOBAL)

# 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
# arguments. Only one source file is currently supported.
#
# Arch-specific flags will be added automatically. The C_FLAGS argument
# can be used to pass additional compiler flags to the compilation of
# the source file.
#
# Example usage:
# add_llext_target(hello_world
# OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
# SOURCES ${PROJECT_SOURCE_DIR}/src/llext/hello_world.c
# C_FLAGS -Werror
# )
# will compile the source file src/llext/hello_world.c to a file
# ${PROJECT_BINARY_DIR}/hello_world.llext, adding -Werror to the compilation.
#
function(add_llext_target target_name)
set(single_args OUTPUT)
set(multi_args SOURCES;C_FLAGS)
cmake_parse_arguments(PARSE_ARGV 1 LLEXT "${options}" "${single_args}" "${multi_args}")

# Check that the llext subsystem is enabled for this build
if (NOT CONFIG_LLEXT)
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 list length must currently be 1
list(LENGTH LLEXT_SOURCES source_count)
if(NOT source_count EQUAL 1)
message(FATAL_ERROR "add_llext_target: only one source file is supported")
endif()

set(output_file ${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}
)

# Compile the source file to an .llext file
if(CONFIG_ARM)
list(PREPEND LLEXT_C_FLAGS "-mlong-calls" "-mthumb")
add_custom_command(OUTPUT ${output_file}
COMMAND ${CMAKE_C_COMPILER} ${LLEXT_C_FLAGS} -c
-I ${ZEPHYR_BASE}/include
-imacros ${AUTOCONF_H}
-o ${output_file}
${source_file}
DEPENDS ${source_file}
)
elseif(CONFIG_XTENSA)
list(PREPEND LLEXT_C_FLAGS "-shared" "-fPIC" "-nostdlib" "-nodefaultlibs")
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)
add_custom_command(OUTPUT ${output_file}
COMMAND ${CMAKE_C_COMPILER} ${LLEXT_C_FLAGS}
-I ${ZEPHYR_BASE}/include
-imacros ${AUTOCONF_H}
-o ${pre_output_file}
${source_file}
COMMAND ${CROSS_COMPILE}strip -R .xt.*
-o ${output_file}
${pre_output_file}
DEPENDS ${source_file}
)
else()
message(FATAL_ERROR "add_llext_target: unsupported architecture")
endif()
endfunction()
3 changes: 3 additions & 0 deletions cmake/modules/zephyr_default.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ list(APPEND zephyr_cmake_modules dts)
list(APPEND zephyr_cmake_modules kconfig)
list(APPEND zephyr_cmake_modules soc)

# Include rules for building llexts
list(APPEND zephyr_cmake_modules llext)

foreach(component ${SUB_COMPONENTS})
if(NOT ${component} IN_LIST zephyr_cmake_modules)
message(FATAL_ERROR
Expand Down
34 changes: 7 additions & 27 deletions tests/subsys/llext/hello_world/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,14 @@ project(hello_world)

if(NOT CONFIG_MODULES OR CONFIG_LLEXT_TEST_HELLO STREQUAL "m")

# TODO check which architecture is being used
if(CONFIG_ARM)
set(CMAKE_C_FLAGS "-mlong-calls" "-mthumb")
set(llext_src_file ${PROJECT_SOURCE_DIR}/hello_world.c)
set(llext_bin_file ${PROJECT_BINARY_DIR}/hello_world.llext)

add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -c
-I ${PROJECT_SOURCE_DIR}/../../../../include
-imacros${PROJECT_BINARY_DIR}/../zephyr/include/generated/autoconf.h
-o ${PROJECT_BINARY_DIR}/hello_world.llext
${PROJECT_SOURCE_DIR}/hello_world.c
)
elseif(CONFIG_XTENSA)
set(CMAKE_C_FLAGS "-shared" "-fPIC" "-nostdlib" "-nodefaultlibs")
add_llext_target(hello_world
OUTPUT ${llext_bin_file}
SOURCES ${llext_src_file}
)

add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS}
-I ${PROJECT_SOURCE_DIR}/../../../../include
-imacros${PROJECT_BINARY_DIR}/../zephyr/include/generated/autoconf.h
-o ${PROJECT_BINARY_DIR}/hello_world.pre.llext
${PROJECT_SOURCE_DIR}/hello_world.c
COMMAND ${CROSS_COMPILE}strip -R .xt.*
-o ${PROJECT_BINARY_DIR}/hello_world.llext
${PROJECT_BINARY_DIR}/hello_world.pre.llext
)
endif()

set(HELLO_WORLD_LLEXT ${PROJECT_BINARY_DIR}/hello_world.llext PARENT_SCOPE)

add_custom_target(hello_world DEPENDS ${PROJECT_BINARY_DIR}/hello_world.llext)
set(HELLO_WORLD_LLEXT ${llext_bin_file} PARENT_SCOPE)

endif()

0 comments on commit 12cdb55

Please sign in to comment.