Skip to content

Commit 5ccbd56

Browse files
committed
llext: fix auxiliary module ordering
Fully automated module dependency tree generation isn't planned for SOF yet, so for now we do this manually. At the moment the sorting is completely random, relying on Python's os.scandir() output. This patch makes it possible to order auxiliary LLEXT modules explicitly. It supports up to 9 dependency levels with level 1 being the most shallow one, i.e. only end-user modules can depend on it. If any level 1 modules depend on further modules, those are called "level 2" modules etc. For this llext targets in respective CMakeLists.txt files have to be called, e.g. "aux1_iir" - see existing examples. This then guarantees correct ordering and successful run-time symbol resolution. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent b94ee8f commit 5ccbd56

4 files changed

Lines changed: 77 additions & 72 deletions

File tree

scripts/xtensa-build-zephyr.py

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import dataclasses
4141
import concurrent.futures as concurrent
4242
import tarfile
43+
import re
4344

4445
from west import configuration as west_config
4546

@@ -967,73 +968,77 @@ def install_lib(platform, sof_output_dir, abs_build_dir, platform_wconfig):
967968

968969
sof_lib_dir.mkdir(parents=True, exist_ok=True)
969970

970-
with os.scandir(str(abs_build_dir)) as iter:
971-
for entry in iter:
972-
if (not entry.is_dir or
973-
not entry.name.endswith('_llext')):
974-
continue
975-
976-
entry_path = pathlib.Path(entry.path)
977-
978-
uuids = entry_path / 'llext.uuid'
979-
if not os.path.exists(uuids):
980-
print(f"Directory {entry.name} has no llext.uuid file. Skipping.")
981-
continue
971+
dirlist = [d for d in os.listdir(str(abs_build_dir)) if os.path.isdir(abs_build_dir / d)]
972+
# Find all auxiliary modules, they're called "aux1_", "aux2_", etc.,
973+
# where lower numbers mean fewer dependent levels, so we need to sort
974+
# them in reversed order to have all dependencies satisfied
975+
pattern_aux = re.compile(r'^aux\d_.+_llext$')
976+
aux = sorted([d for d in dirlist if pattern_aux.match(d)], reverse=True)
977+
llext_dirs = [d for d in dirlist if d.endswith('_llext') and d not in aux]
978+
finallist = aux + llext_dirs
979+
980+
for entry in finallist:
981+
entry_path = abs_build_dir / entry
982+
983+
uuids = entry_path / 'llext.uuid'
984+
if not os.path.exists(uuids):
985+
print(f"Directory {entry} has no llext.uuid file. Skipping.")
986+
continue
982987

983-
# replace '_llext' with '.llext', e.g.
984-
# eq_iir_llext/eq_iir.llext
985-
llext_base = entry.name[:-6]
986-
llext_file = llext_base + '.llext'
987-
lib_name = ''
988-
989-
lib_fname = entry_path / 'lib_name.txt'
990-
if os.path.exists(lib_fname):
991-
with open(lib_fname, 'r') as libs_f:
992-
lib_name = libs_f.read()
993-
if lib_name not in libs.keys():
994-
libs[lib_name] = []
995-
libs[lib_name].append(str(entry_path / llext_file))
996-
else:
997-
dst = sof_lib_dir / llext_file
998-
999-
rimage_cfg = entry_path / 'rimage_config.toml'
1000-
llext_input = entry_path / (llext_base + '.llext')
1001-
llext_output = entry_path / (llext_file + '.ri')
1002-
1003-
# See why the shlex() parsing step is required at
1004-
# https://docs.zephyrproject.org/latest/develop/west/sign.html#rimage
1005-
# and in Zephyr commit 030b740bd1ec
1006-
sign_cmd = [rimage_cmd, "-o", str(llext_output),
1007-
"-e", "-c", str(rimage_cfg),
1008-
"-k", str(signing_key), "-l", "-r"]
1009-
if _ws_args is not None:
1010-
sign_cmd.extend(shlex.split(_ws_args))
1011-
sign_cmd.append(str(llext_input))
1012-
execute_command(sign_cmd, cwd=west_top)
1013-
1014-
# An intuitive way to make this multiline would be
1015-
# with (open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext,
1016-
# open(llext_output.with_suffix('.llext.xman'), 'rb') as fman):
1017-
# but a Python version, used on Windows errored out on this.
1018-
# Thus we're left with a choice between a 150-character
1019-
# long line and an illogical split like this
1020-
with open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, open(
1021-
llext_output.with_suffix('.ri.xman'), 'rb') as fman:
1022-
# Concatenate the manifest and the llext
1023-
shutil.copyfileobj(fman, fdst)
1024-
shutil.copyfileobj(fllext, fdst)
1025-
1026-
# Create symbolic links for all UUIDs
1027-
with open(uuids, 'r') as uuids_f:
1028-
for uuid in uuids_f:
1029-
if os.path.exists(lib_fname):
1030-
if lib_name not in lib_uuids.keys():
1031-
lib_uuids[lib_name] = []
1032-
lib_uuids[lib_name].append(uuid.strip())
1033-
else:
1034-
linkname = uuid.strip() + '.bin'
1035-
symlink_or_copy(sof_lib_dir, llext_file,
1036-
sof_lib_dir, linkname)
988+
# replace '_llext' with '.llext', e.g.
989+
# eq_iir_llext/eq_iir.llext
990+
llext_base = entry[:-6]
991+
llext_file = llext_base + '.llext'
992+
lib_name = ''
993+
994+
lib_fname = entry_path / 'lib_name.txt'
995+
if os.path.exists(lib_fname):
996+
with open(lib_fname, 'r') as libs_f:
997+
lib_name = libs_f.read()
998+
if lib_name not in libs.keys():
999+
libs[lib_name] = []
1000+
libs[lib_name].append(str(entry_path / llext_file))
1001+
else:
1002+
dst = sof_lib_dir / llext_file
1003+
1004+
rimage_cfg = entry_path / 'rimage_config.toml'
1005+
llext_input = entry_path / (llext_base + '.llext')
1006+
llext_output = entry_path / (llext_file + '.ri')
1007+
1008+
# See why the shlex() parsing step is required at
1009+
# https://docs.zephyrproject.org/latest/develop/west/sign.html#rimage
1010+
# and in Zephyr commit 030b740bd1ec
1011+
sign_cmd = [rimage_cmd, "-o", str(llext_output),
1012+
"-e", "-c", str(rimage_cfg),
1013+
"-k", str(signing_key), "-l", "-r"]
1014+
if _ws_args is not None:
1015+
sign_cmd.extend(shlex.split(_ws_args))
1016+
sign_cmd.append(str(llext_input))
1017+
execute_command(sign_cmd, cwd=west_top)
1018+
1019+
# An intuitive way to make this multiline would be
1020+
# with (open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext,
1021+
# open(llext_output.with_suffix('.llext.xman'), 'rb') as fman):
1022+
# but a Python version, used on Windows errored out on this.
1023+
# Thus we're left with a choice between a 150-character
1024+
# long line and an illogical split like this
1025+
with open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, open(
1026+
llext_output.with_suffix('.ri.xman'), 'rb') as fman:
1027+
# Concatenate the manifest and the llext
1028+
shutil.copyfileobj(fman, fdst)
1029+
shutil.copyfileobj(fllext, fdst)
1030+
1031+
# Create symbolic links for all UUIDs
1032+
with open(uuids, 'r') as uuids_f:
1033+
for uuid in uuids_f:
1034+
if os.path.exists(lib_fname):
1035+
if lib_name not in lib_uuids.keys():
1036+
lib_uuids[lib_name] = []
1037+
lib_uuids[lib_name].append(uuid.strip())
1038+
else:
1039+
linkname = uuid.strip() + '.bin'
1040+
symlink_or_copy(sof_lib_dir, llext_file,
1041+
sof_lib_dir, linkname)
10371042

10381043
lib_install_dir = sof_output_dir / platform
10391044
if args.key_type_subdir != "none":

src/math/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ if(CONFIG_BINARY_LOGARITHM_FIXED)
4444
endif()
4545

4646
if(CONFIG_MATH_FIR STREQUAL "m")
47-
add_subdirectory(fir_llext ${PROJECT_BINARY_DIR}/fir_llext)
48-
add_dependencies(app fir)
47+
add_subdirectory(fir_llext ${PROJECT_BINARY_DIR}/aux1_fir_llext)
48+
add_dependencies(app aux1_fir)
4949
elseif(CONFIG_MATH_FIR)
5050
list(APPEND base_files fir_generic.c fir_hifi2ep.c fir_hifi3.c fir_hifi5.c)
5151
endif()
@@ -55,8 +55,8 @@ if(CONFIG_MATH_FFT)
5555
endif()
5656

5757
if(CONFIG_MATH_IIR STREQUAL "m")
58-
add_subdirectory(iir_llext ${PROJECT_BINARY_DIR}/iir_llext)
59-
add_dependencies(app iir)
58+
add_subdirectory(iir_llext ${PROJECT_BINARY_DIR}/aux1_iir_llext)
59+
add_dependencies(app aux1_iir)
6060
elseif(CONFIG_MATH_IIR)
6161
if(CONFIG_MATH_IIR_DF2T)
6262
list(APPEND base_files iir_df2t_generic.c iir_df2t_hifi3.c iir_df2t.c)

src/math/fir_llext/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright (c) 2024 Intel Corporation.
22
# SPDX-License-Identifier: Apache-2.0
33

4-
sof_llext_build("fir"
4+
sof_llext_build("aux1_fir"
55
SOURCES fir_common.c
66
../fir_generic.c
77
../fir_hifi2ep.c

src/math/iir_llext/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ else()
1515
endif()
1616

1717
if(CONFIG_MATH_IIR_DF1 OR CONFIG_MATH_IIR_DF2T)
18-
sof_llext_build("iir"
18+
sof_llext_build("aux1_iir"
1919
SOURCES iir.c ${df1} ${df2t}
2020
LIB openmodules
2121
)

0 commit comments

Comments
 (0)