Skip to content

Commit a004c9b

Browse files
committed
llext-edk: capture full build properties for EDK export
The current implementation of the LLEXT EDK exports only a partial set of compiler settings to the EDK build system, specifically only the ones defined by the Zephyr core (the 'zephyr_interface' target). Extending this to include application and module-specific settings (from the 'app' target and its dependencies) is tricky, because: - while evaluating the main CMakeLists.txt, the 'app' target is not fully configured yet, and - using generator expressions is not possible due to CMake not allowing expansion of $<COMPILE_LANGUAGE:...> outside of a proper compile context. To work around this, this change introduces a new CMake subdirectory (misc/llext_edk) that creates a dummy target which imports the build configuration from 'app', but overrides the C compile rules to simply output the resulting properties (defines, include directories, flags) to text files. The EDK generation script then reads those text files to get the full set of build properties, and includes them in the EDK tarball. Signed-off-by: Luca Burelli <[email protected]>
1 parent 36be75a commit a004c9b

File tree

4 files changed

+53
-22
lines changed

4 files changed

+53
-22
lines changed

CMakeLists.txt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,19 +2288,14 @@ if(CONFIG_LLEXT_EDK)
22882288
endif()
22892289
set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.${llext_edk_extension})
22902290

2291-
# TODO maybe generate flags for C CXX ASM
2292-
zephyr_get_compile_definitions_for_lang(C zephyr_defs)
2293-
zephyr_get_compile_options_for_lang(C zephyr_flags)
2294-
2295-
set(llext_edk_cflags ${zephyr_defs} ${zephyr_flags})
2296-
22972291
# Export current settings for use in LLEXT EDK generation
22982292
build_info(llext-edk file PATH ${llext_edk_file})
2299-
build_info(llext-edk cflags VALUE ${llext_edk_cflags})
2300-
build_info(llext-edk include-dirs VALUE "$<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>")
23012293
build_info(llext-edk remove-cflags VALUE ${LLEXT_REMOVE_FLAGS} ${LLEXT_EDK_REMOVE_FLAGS})
23022294
build_info(llext-edk append-cflags VALUE ${LLEXT_APPEND_FLAGS} ${LLEXT_EDK_APPEND_FLAGS} -DLL_EXTENSION_BUILD)
23032295

2296+
# Generate the compiler flag files that will be used by the EDK
2297+
add_subdirectory(misc/llext_edk)
2298+
23042299
add_custom_command(
23052300
OUTPUT ${llext_edk_file}
23062301
# Regenerate syscalls in case CONFIG_LLEXT_EDK_USERSPACE_ONLY
@@ -2318,7 +2313,7 @@ if(CONFIG_LLEXT_EDK)
23182313
${SYSCALL_SPLIT_TIMEOUT_ARG}
23192314
COMMAND ${CMAKE_COMMAND}
23202315
-P ${ZEPHYR_BASE}/cmake/llext-edk.cmake
2321-
DEPENDS ${logical_target_for_zephyr_elf} ${syscalls_json} build_info_yaml_saved
2316+
DEPENDS ${logical_target_for_zephyr_elf} ${syscalls_json} build_info_yaml_saved llext_edk_build_props
23222317
COMMAND_EXPAND_LISTS
23232318
)
23242319
add_custom_target(llext-edk DEPENDS ${llext_edk_file})

cmake/llext-edk.cmake

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# This script generates a tarball containing all headers and flags necessary to
55
# build an llext extension. It does so by copying all headers accessible from
6-
# INTERFACE_INCLUDE_DIRECTORIES and generating a Makefile.cflags file (and a
6+
# a C compiler command line and generating a Makefile.cflags file (and a
77
# cmake.cflags one) with all flags necessary to build the extension.
88
#
99
# The tarball can be extracted and used in the extension build system to include
@@ -152,19 +152,34 @@ if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID)
152152
"The LLEXT EDK is not compatible with CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID.")
153153
endif()
154154

155+
set(build_flags_dir ${PROJECT_BINARY_DIR}/misc/llext_edk)
155156
set(build_info_file ${PROJECT_BINARY_DIR}/../build_info.yml)
156157
yaml_load(FILE ${build_info_file} NAME build_info)
157158

158-
yaml_get(llext_edk_cflags NAME build_info KEY cmake llext-edk cflags)
159+
# process C flags
160+
file(READ ${build_flags_dir}/c_flags.txt llext_edk_c_flags_raw)
161+
string(STRIP ${llext_edk_c_flags_raw} llext_edk_c_flags)
162+
string(REPLACE " " ";" llext_edk_cflags "${llext_edk_c_flags}")
159163
yaml_get(llext_remove_cflags NAME build_info KEY cmake llext-edk remove-cflags)
160164
yaml_get(llext_append_cflags NAME build_info KEY cmake llext-edk append-cflags)
161165
foreach(item IN_LIST ${llext_remove_cflags})
162166
list(FILTER llext_edk_cflags EXCLUDE REGEX "^${item}$")
163167
endforeach()
164168
list(APPEND llext_edk_cflags ${llext_append_cflags})
165169

170+
# process C definitions
171+
file(READ ${build_flags_dir}/c_defs.txt llext_edk_c_defs_raw)
172+
string(STRIP ${llext_edk_c_defs_raw} llext_edk_c_defs)
173+
string(REPLACE " " ";" llext_edk_c_defs "${llext_edk_c_defs}")
174+
list(PREPEND llext_edk_cflags ${llext_edk_c_defs})
175+
176+
# process C include directories
177+
file(READ ${build_flags_dir}/c_incs.txt llext_edk_c_incs_raw)
178+
string(STRIP ${llext_edk_c_incs_raw} llext_edk_c_incs)
179+
string(REPLACE " " ";" llext_edk_c_incs "${llext_edk_c_incs}")
180+
list(TRANSFORM llext_edk_c_incs REPLACE "^-I" "")
181+
166182
yaml_get(llext_edk_file NAME build_info KEY cmake llext-edk file)
167-
yaml_get(INTERFACE_INCLUDE_DIRECTORIES NAME build_info KEY cmake llext-edk include-dirs)
168183
yaml_get(APPLICATION_SOURCE_DIR NAME build_info KEY cmake application source-dir)
169184
yaml_get(WEST_TOPDIR NAME build_info KEY west topdir)
170185

@@ -217,8 +232,8 @@ set(llext_edk_cflags ${new_cflags})
217232
list(APPEND base_flags ${llext_edk_cflags} ${imacros})
218233

219234
file(MAKE_DIRECTORY ${llext_edk_inc})
220-
foreach(dir ${INTERFACE_INCLUDE_DIRECTORIES})
221-
if (NOT EXISTS ${dir})
235+
foreach(dir ${llext_edk_c_incs})
236+
if(NOT EXISTS ${dir})
222237
continue()
223238
endif()
224239

misc/llext_edk/CMakeLists.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2025 Arduino SA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# This CMake script is used to capture the full set of build properties for the
5+
# Zephyr 'app' target so that it can be properly exported by the EDK build
6+
# system.
7+
8+
# Getting the whole list of build properties via CMake functions is tricky.
9+
# The 'app' target is not fully configured at the time Zephyr scripts are
10+
# included, so querying its properties directly would yield incomplete results.
11+
# However, using CMake generator expressions is also forbidden, since the
12+
# properties include $<COMPILE_LANGUAGE:...> entries, and CMake does not know
13+
# how to resolve those outside of a proper compile context.
14+
15+
# To work around this, the following code creates a dummy target that imports
16+
# build configuration from 'app', but overrides the C compile rules to simply
17+
# output the resulting properties to text files. The EDK will then read those
18+
# text files to get the full set of build properties.
19+
20+
unset(CMAKE_C_COMPILER_LAUNCHER)
21+
unset(CMAKE_DEPFILE_FLAGS_C)
22+
set(CMAKE_C_COMPILE_OBJECT
23+
"${CMAKE_COMMAND} -E echo '<DEFINES>' > ${CMAKE_CURRENT_BINARY_DIR}/c_defs.txt"
24+
"${CMAKE_COMMAND} -E echo '<INCLUDES>' > ${CMAKE_CURRENT_BINARY_DIR}/c_incs.txt"
25+
"${CMAKE_COMMAND} -E echo '<FLAGS>' > ${CMAKE_CURRENT_BINARY_DIR}/c_flags.txt"
26+
"${CMAKE_C_COMPILE_OBJECT}")
27+
28+
add_library(llext_edk_build_props ${ZEPHYR_BASE}/misc/empty_file.c)
29+
target_link_libraries(llext_edk_build_props PUBLIC app)

scripts/schemas/build-schema.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,8 @@ mapping:
8585
llext-edk:
8686
type: map
8787
mapping:
88-
cflags:
89-
type: seq
90-
sequence:
91-
- type: str
9288
file:
9389
type: str
94-
include-dirs:
95-
type: seq
96-
sequence:
97-
- type: str
9890
remove-cflags:
9991
type: seq
10092
sequence:

0 commit comments

Comments
 (0)