Skip to content

Commit dfc4205

Browse files
lrgirdwoclaude
andcommitted
ffmpeg_dec: support cross-building FFmpeg with the LLVM xt-clang
Add a clang branch to the FFmpeg cross-build so the module can be built with the LLVM Xtensa clang (needed for any HiFi intrinsics -- the Zephyr-SDK GCC ships no xt_hifi/ae_* intrinsics header at all). clang is a generic driver, so unlike the target-specific GCC it needs the target/core/sysroot spelled out, uses the Zephyr-SDK GNU binutils (ar/as/nm/objcopy), and cannot link the bare-metal configure *test* executables (no default crt), so those link via the GNU gcc (--ld). All values are derived from CMAKE_AR (GNU binutils even under clang): cross-prefix, sysroot, and -mcpu=<core> from the triple. Also disables auto/SLP vectorisation: the LLVM Xtensa backend cannot lower the v2i32 bswap FFmpeg byteswap code gets SLP-vectorised into ("Cannot select: v2i32 = bswap"), and it buys nothing (no packed float SIMD codegen on Xtensa anyway). The GCC path is unchanged (guarded on CMAKE_C_COMPILER_ID) and re-verified green: pristine ptl AAC build -> ARCH_XTENSA=1, float_dsp_init.o compiled, ffmpeg_dec.llext linked. The clang recipe is validated at the FFmpeg-configure/build level: a standalone decoder-only cross-build (avcodec+avutil+swresample, FLAC) with ~/work/llvm-project clang links clean and produces elf32-xtensa-le objects. A full firmware clang build additionally requires the Zephyr LLVM toolchain variant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 95e9fd3 commit dfc4205

1 file changed

Lines changed: 38 additions & 9 deletions

File tree

src/audio/ffmpeg_dec/ffmpeg.cmake

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,46 @@ if(CONFIG_FFMPEG_BUILD_AVFILTER)
6868
message(STATUS "ffmpeg_dec: enabling avfilter, filters [${_ff_filt_csv}]")
6969
endif()
7070

71-
# --- 3. Derive the cross toolchain prefix from the Zephyr target compiler ---
72-
# e.g. .../bin/xtensa-intel_ace30_ptl_zephyr-elf-gcc
73-
# -> prefix .../bin/xtensa-intel_ace30_ptl_zephyr-elf-
74-
get_filename_component(_tc_dir "${CMAKE_C_COMPILER}" DIRECTORY)
75-
get_filename_component(_tc_name "${CMAKE_C_COMPILER}" NAME)
76-
string(REGEX REPLACE "gcc$" "" _tc_prefix_name "${_tc_name}")
77-
set(_ff_cross_prefix "${_tc_dir}/${_tc_prefix_name}")
78-
71+
# --- 3. Derive the cross toolchain + per-compiler cross flags ---
7972
# GCC 14 (Zephyr SDK) promotes these to errors; FFmpeg 7.x trips them.
8073
set(_ff_extra_cflags "-fPIC -Wno-error=incompatible-pointer-types -Wno-error=implicit-function-declaration")
8174

75+
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
76+
# LLVM/xt-clang build. clang is a generic driver, so unlike the target-
77+
# specific GCC it needs the target/core/sysroot spelled out, it uses the
78+
# Zephyr-SDK GNU binutils for ar/as/nm/objcopy, and it cannot link the bare-
79+
# metal configure *test* executables itself (no default crt/linker script) --
80+
# so those are linked with the GNU gcc via --ld. We only ever build .a
81+
# archives (ar), so the linker choice affects configure tests only.
82+
# Everything is derived from CMAKE_AR (Zephyr uses GNU binutils even under
83+
# clang), e.g. .../bin/xtensa-intel_ace30_ptl_zephyr-elf-ar:
84+
string(REGEX REPLACE "ar$" "" _ff_cross_prefix "${CMAKE_AR}") # ...-elf-
85+
get_filename_component(_tc_dir "${CMAKE_AR}" DIRECTORY) # .../bin
86+
get_filename_component(_ff_gnuroot "${_tc_dir}" DIRECTORY) # gnu root
87+
get_filename_component(_ff_triple "${_ff_cross_prefix}" NAME) # ...-elf-
88+
string(REGEX REPLACE "-$" "" _ff_triple "${_ff_triple}") # triple
89+
set(_ff_sysroot "${_ff_gnuroot}/${_ff_triple}")
90+
# core name for -mcpu: triple minus the xtensa- prefix and _zephyr-elf suffix
91+
# (xtensa-intel_ace30_ptl_zephyr-elf -> intel_ace30_ptl).
92+
string(REGEX REPLACE "^xtensa-" "" _ff_core "${_ff_triple}")
93+
string(REGEX REPLACE "_zephyr-elf$" "" _ff_core "${_ff_core}")
94+
set(_ff_cc "${CMAKE_C_COMPILER} --target=xtensa -mcpu=${_ff_core} --sysroot=${_ff_sysroot}")
95+
set(_ff_ld "${_ff_cross_prefix}gcc")
96+
# The LLVM Xtensa backend cannot lower the SLP-vectorised v2i32 bswap that
97+
# FFmpeg byteswap code produces ("Cannot select: v2i32 = bswap"); disable
98+
# vectorisation to avoid it (and it buys nothing -- no packed float SIMD).
99+
set(_ff_extra_cflags "${_ff_extra_cflags} -fno-vectorize -fno-slp-vectorize")
100+
else()
101+
# GCC (Zephyr SDK): target-specific driver, brings its own sysroot + crt.
102+
# e.g. .../bin/xtensa-intel_ace30_ptl_zephyr-elf-gcc -> prefix ...-elf-
103+
get_filename_component(_tc_dir "${CMAKE_C_COMPILER}" DIRECTORY)
104+
get_filename_component(_tc_name "${CMAKE_C_COMPILER}" NAME)
105+
string(REGEX REPLACE "gcc$" "" _tc_prefix_name "${_tc_name}")
106+
set(_ff_cross_prefix "${_tc_dir}/${_tc_prefix_name}")
107+
set(_ff_cc "${CMAKE_C_COMPILER}")
108+
set(_ff_ld "${CMAKE_C_COMPILER}")
109+
endif()
110+
82111
set(FFMPEG_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg-install" CACHE INTERNAL "ffmpeg_dec libs")
83112

84113
# Hot/cold split: GCC emits av_cold (init/setup) functions into .text.unlikely.
@@ -179,7 +208,7 @@ ExternalProject_Add(ffmpeg_ext
179208
<SOURCE_DIR>/configure
180209
--prefix=${FFMPEG_INSTALL_DIR}
181210
--enable-cross-compile --target-os=none --arch=xtensa
182-
--cross-prefix=${_ff_cross_prefix} --cc=${CMAKE_C_COMPILER}
211+
--cross-prefix=${_ff_cross_prefix} "--cc=${_ff_cc}" "--ld=${_ff_ld}"
183212
# NOTE: do NOT pass --disable-asm. FFmpeg treats every per-arch
184213
# optimisation dir (incl. our C-intrinsic libavutil/xtensa/) as
185214
# "asm"; --disable-asm forces arch=c and drops them. There is no

0 commit comments

Comments
 (0)