Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/xtensa/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ if(CONFIG_SOC_FAMILY_ESPRESSIF_ESP32)
)
else()
set(XTENSA_CONFIG_HAL_INCLUDE_DIR
-I${ZEPHYR_XTENSA_MODULE_DIR}/zephyr/soc/${CONFIG_SOC}
-I${ZEPHYR_XTENSA_MODULE_DIR}/zephyr/soc/${CONFIG_SOC_TOOLCHAIN_NAME}
)
endif()

Expand Down
9 changes: 8 additions & 1 deletion cmake/compiler/clang/compiler_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ set_compiler_property(PROPERTY diagnostic -fcolor-diagnostics)
# clang flag to disable macro backtrace in diagnostics (can't fully disable it, so limit to 1)
set_compiler_property(PROPERTY no_track_macro_expansion "-fmacro-backtrace-limit=1")

set_compiler_property(PROPERTY no_global_merge "-mno-global-merge")
# -mno-global-merge is only supported by Clang on ARM targets.
# On other architectures (e.g. Xtensa) it triggers:
# warning: argument unused during compilation: '-mno-global-merge'
if("${ARCH}" STREQUAL "arm" OR "${ARCH}" STREQUAL "arm64")
set_compiler_property(PROPERTY no_global_merge "-mno-global-merge")
else()
set_compiler_property(PROPERTY no_global_merge "")
endif()

set_compiler_property(PROPERTY specs)
2 changes: 2 additions & 0 deletions cmake/linker/ld/linker_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ check_set_linker_property(TARGET linker PROPERTY baremetal
-nostdlib
-static
-znoexecstack
${LINKERFLAGPREFIX},--no-warn-rwx-segments
${LINKERFLAGPREFIX},--no-warn-execstack
${LINKERFLAGPREFIX},-X
${LINKERFLAGPREFIX},-N
)
Expand Down
16 changes: 13 additions & 3 deletions cmake/linker/ld/target.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,13 @@
set(link_libraries "<OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${zephyr_std_libs}")
set(common_link "<LINK_FLAGS> ${link_libraries}")

set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
if(DEFINED XTENSA_GCC)
set(CMAKE_ASM_LINK_EXECUTABLE "${XTENSA_GCC} <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
set(CMAKE_C_LINK_EXECUTABLE "${XTENSA_GCC} <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
else()
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
endif()

set(cpp_link "${common_link}")
if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host")
Expand All @@ -167,7 +172,12 @@
set(cpp_link "<LINK_FLAGS> ${CRTBEGIN_PATH} ${link_libraries} ${CRTEND_PATH}")
endif()
endif()
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${cpp_link}")

Check failure on line 175 in cmake/linker/ld/target.cmake

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

TRAILING_WHITESPACE

cmake/linker/ld/target.cmake:175 trailing whitespace See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details.
if(DEFINED XTENSA_GCC)
set(CMAKE_CXX_LINK_EXECUTABLE "${XTENSA_GCC} <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${cpp_link}")
else()
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${cpp_link}")
endif()
endmacro()

# Function to map compiler flags into suitable linker flags
Expand Down
18 changes: 18 additions & 0 deletions cmake/toolchain/llvm/generic.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: Apache-2.0

set(COMPILER clang)
set(LINKER ld)
set(BINTOOLS gnu)

zephyr_get(LLVM_TOOLCHAIN_PATH)
if(LLVM_TOOLCHAIN_PATH)
set(TOOLCHAIN_HOME ${LLVM_TOOLCHAIN_PATH}/bin/)
endif()

# When using the Zephyr SDK as our binutils provider, the SDK sysroot contains
# both newlib and picolibc headers. Advertise this to Kconfig so that
# PICOLIBC_SUPPORTED / NEWLIB_LIBC_SUPPORTED are set *before* kconfig.cmake
# runs (generic.cmake is loaded via FindHostTools during the dts phase, whereas
# target.cmake is loaded much later via FindTargetTools in the kernel phase).
set(TOOLCHAIN_HAS_PICOLIBC y CACHE INTERNAL "True if toolchain supports picolibc")
set(TOOLCHAIN_HAS_NEWLIB y CACHE INTERNAL "True if toolchain supports newlib")
262 changes: 262 additions & 0 deletions cmake/toolchain/llvm/target.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# SPDX-License-Identifier: Apache-2.0

if(CONFIG_LLVM_USE_LD)
set(LINKER ld)
elseif(CONFIG_LLVM_USE_LLD)
set(LINKER lld)
endif()

if("${ARCH}" STREQUAL "arm")
if(DEFINED CONFIG_ARMV8_M_MAINLINE)
# ARMv8-M mainline is ARMv7-M with additional features from ARMv8-M.
set(triple armv8m.main-none-eabi)
elseif(DEFINED CONFIG_ARMV8_M_BASELINE)
# ARMv8-M baseline is ARMv6-M with additional features from ARMv8-M.
set(triple armv8m.base-none-eabi)
elseif(DEFINED CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
# ARMV7_M_ARMV8_M_MAINLINE means that ARMv7-M or backward compatible ARMv8-M
# processor is used.
set(triple armv7m-none-eabi)
elseif(DEFINED CONFIG_ARMV6_M_ARMV8_M_BASELINE)
# ARMV6_M_ARMV8_M_BASELINE means that ARMv6-M or ARMv8-M supporting the
# Baseline implementation processor is used.
set(triple armv6m-none-eabi)
else()
# Default ARM target supported by all processors.
set(triple arm-none-eabi)
endif()
elseif("${ARCH}" STREQUAL "arm64")
set(triple aarch64-none-elf)
elseif("${ARCH}" STREQUAL "x86")
if(CONFIG_64BIT)
set(triple x86_64-pc-none-elf)
else()
set(triple i686-pc-none-elf)
endif()
elseif("${ARCH}" STREQUAL "riscv")
if(CONFIG_64BIT)
set(triple riscv64-unknown-elf)
else()
set(triple riscv32-unknown-elf)
endif()
elseif("${ARCH}" STREQUAL "xtensa")
# Xtensa uses Clang for compilation with GCC assembler/linker from Zephyr SDK.
# The target triple encodes the specific Xtensa core variant.
#
# Two names are involved per SoC:
# * XTENSA_TOOLCHAIN_TARGET - Zephyr SDK toolchain target dir name
# (matches CONFIG_SOC_TOOLCHAIN_NAME),
# e.g. "intel_ace30_ptl".
# * XTENSA_CORE_ID - upstream LLVM Xtensa backend -mcpu name,
# typically "<vendor>_<id>_adsp",
# e.g. "intel_ace30_adsp".
#
# Both can be overridden via environment variables. If unset, they are
# derived from CONFIG_SOC_TOOLCHAIN_NAME and a small mapping table for
# the SoCs that ship with mismatched SDK/LLVM names.

set(XTENSA_TOOLCHAIN_TARGET $ENV{XTENSA_TOOLCHAIN_TARGET})
if(NOT XTENSA_TOOLCHAIN_TARGET)
if(CONFIG_SOC_TOOLCHAIN_NAME)
set(XTENSA_TOOLCHAIN_TARGET "${CONFIG_SOC_TOOLCHAIN_NAME}")
else()
# Fallback for boards that don't set CONFIG_SOC_TOOLCHAIN_NAME yet.
set(XTENSA_TOOLCHAIN_TARGET "intel_ace30_ptl")
endif()
endif()

set(XTENSA_CORE_ID $ENV{XTENSA_CORE_ID})
if(NOT XTENSA_CORE_ID)
# Map Zephyr SDK toolchain target -> upstream LLVM Xtensa -mcpu name.
# Only entries whose names differ between the SDK and LLVM are listed;
# anything not in this table is assumed to be identical in both.
set(_xtensa_sdk_to_llvm_cpu
# Intel ADSP
intel_ace15_mtpm intel_ace15_adsp
intel_ace40 intel_ace40_adsp
intel_ace30_ptl intel_ace30_adsp
)
list(FIND _xtensa_sdk_to_llvm_cpu "${XTENSA_TOOLCHAIN_TARGET}" _idx)
if(_idx GREATER -1)
math(EXPR _val_idx "${_idx} + 1")
list(GET _xtensa_sdk_to_llvm_cpu ${_val_idx} XTENSA_CORE_ID)
else()
# SDK target name matches the LLVM -mcpu name (true for most
# AMD/MTK/NXP ADSP cores and dc233c / sample_controller*).
set(XTENSA_CORE_ID "${XTENSA_TOOLCHAIN_TARGET}")
endif()
unset(_xtensa_sdk_to_llvm_cpu)
unset(_idx)
unset(_val_idx)
endif()

set(triple xtensa-${XTENSA_TOOLCHAIN_TARGET}_zephyr-elf)
set(XTENSA_CLANG_MCPU ${XTENSA_CORE_ID})

# Use GCC assembler/linker from Zephyr SDK
set(LINKER ld)
set(BINTOOLS gnu)

# Configure cross-compile prefix for binutils (assembler, linker, objcopy, etc.)
set(CROSS_COMPILE_TARGET xtensa-${XTENSA_TOOLCHAIN_TARGET}_zephyr-elf)
if(DEFINED ZEPHYR_SDK_INSTALL_DIR)
set(CROSS_COMPILE $ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-)
endif()

# Clang-specific flags for Xtensa
list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${XTENSA_CLANG_MCPU})
# Define __XCC__ so SOF's HiFi detection logic (format.h, fft.h, fir_config.h
# etc.) recognises our LLVM Clang as an Xtensa compiler with HiFi support and
# enters the "#if defined __XCC__" branches that read XCHAL_HAVE_HIFIx from
# <xtensa/config/core-isa.h>.
# Also define __XCC_CLANG__ so the CAVS-family core-isa.h files (tgl, apl,
# cnl, icl) can whitelist LLVM without triggering their "#error xcc should
# not use this header" guard (see modules/hal/xtensa patch below).
list(APPEND TOOLCHAIN_C_FLAGS -D__XCC__ -D__XCC_CLANG__)
# Use the GCC assembler for all code — the integrated assembler can't
# encode HiFi pseudo instructions (AE_MOVDA32X2 etc).
list(APPEND TOOLCHAIN_C_FLAGS -fno-integrated-as)
if(CONFIG_COMPILER_CODEGEN_VLIW_ENABLED)
# Add +flix strictly to compile steps to prevent ld from misinterpreting +flix as an object file
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX,ASM>:SHELL:-Xclang -target-feature -Xclang +flix>")
endif()
# Place Xtensa literal pools inline with their parent text sections.
# Without this, the GNU assembler places all literals in a single .literal
# section, which is unreachable from .imr functions in a different MEMORY region.
# Also enable --longcalls so the assembler converts call4/call8/call12 into
# l32r+callxN when the target may be out of the ±512KB direct call range.
# This fixes cross-section calls (e.g. .text → .imr) that the linker
# cannot relax without R_XTENSA_ASM_EXPAND relocations.
list(APPEND TOOLCHAIN_C_FLAGS -Wa,--text-section-literals -Wa,--longcalls)
# Force DWARFv4 debug info for compatibility with Zephyr's kobject scanner
# (gen_kobject_list.py). Clang defaults to DWARFv5 which the scanner can't parse.
list(APPEND TOOLCHAIN_C_FLAGS -gdwarf-4)
# -B paths: first for assembler (as), second for GCC linker driver
list(APPEND TOOLCHAIN_C_FLAGS -B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET}/bin)
list(APPEND TOOLCHAIN_C_FLAGS -B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin)
# Add the GCC SDK's xtensa include path for core-isa.h and related HAL headers
# needed by HiFi code (format_hifi3.h etc.)
file(GLOB GCC_XTENSA_INCLUDE "$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/lib/gcc/${CROSS_COMPILE_TARGET}/*/include")
list(APPEND TOOLCHAIN_C_FLAGS -isystem${GCC_XTENSA_INCLUDE})
list(APPEND TOOLCHAIN_C_FLAGS -isystem$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET}/include)



set(SYSROOT_DIR $ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET})

# Pre-set the GNU linker so FindGnuLd doesn't fall back to the host x86 linker
set(GNULD_LINKER $ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-ld.bfd
CACHE FILEPATH "GNU ld linker" FORCE)
set(GNULD_LINKER_IS_BFD ON CACHE BOOL "Linker BFD compatibility" FORCE)

# FLIX VLIW instruction bundling — DISABLED by default.
# The packetizer pass in LLVM generates some invalid instruction pairs
# because we don't fully model the hardware FLIX slot constraints yet.
# To enable manually: add '-Xclang -target-feature -Xclang +flix' to CMAKE_C_FLAGS
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Xclang -target-feature -Xclang +flix" CACHE STRING "" FORCE)

# Ensure the dummy compile test can find the Xtensa assembler and linker.
# NOTE: The Xtensa GCC bin dir must be on PATH for Clang's linker-via-gcc to work.
set(CMAKE_REQUIRED_FLAGS "-B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET}/bin -B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin -mcpu=${XTENSA_CLANG_MCPU} -nostartfiles -nostdlib")

# Force cmake to use the Xtensa linker for all link steps.
# TOOLCHAIN_LD_FLAGS applies to the main zephyr build (via zephyr_ld_options).
# CMAKE_LINKER is needed for sub-targets like LLEXT.
# Add -B paths so clang can find the Xtensa linker/assembler when it drives linking.
set(XTENSA_LD_BFD $ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-ld.bfd)
set(CMAKE_LINKER ${XTENSA_LD_BFD} CACHE FILEPATH "" FORCE)
list(APPEND TOOLCHAIN_LD_FLAGS
-B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET}/bin
-B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin
)
# Generate a custom GCC specs file that removes picolibc.ld auto-inclusion.
# The Zephyr SDK GCC is built with --with-default-libc=picolibc which adds
# -Tpicolibc.ld to every link. picolibc.ld defines a 'flash' MEMORY region
# and AT>flash LMA mappings that conflict with the RAM-only Xtensa memory model.
set(XTENSA_SPECS_FILE "${CMAKE_BINARY_DIR}/xtensa_nopico.specs")
set(_GCC_FOR_SPECS "$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-gcc")
execute_process(
COMMAND ${_GCC_FOR_SPECS} -dumpspecs
OUTPUT_VARIABLE _gcc_specs
)
string(REPLACE "%:if-exists-then-else(%:find-file(picolibc.ld) -Tpicolibc.ld)" "" _gcc_specs "${_gcc_specs}")
file(WRITE "${XTENSA_SPECS_FILE}" "${_gcc_specs}")

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/${CROSS_COMPILE_TARGET}/bin -B$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin -nostartfiles -nodefaultlibs -specs=${XTENSA_SPECS_FILE} -Wl,--noinhibit-exec" CACHE STRING "" FORCE)


# Override compiler_set_linker_properties to use the GCC libgcc path since
# we compile with clang but link with GCC. Clang's --print-libgcc-file-name
# returns the clang compiler-rt path which GCC's ld can't find.
function(compiler_set_linker_properties)
set(_gcc_libdir "$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/lib/gcc/${CROSS_COMPILE_TARGET}/14.3.0")
set_linker_property(PROPERTY lib_include_dir "-L\"${_gcc_libdir}\"")
set_linker_property(PROPERTY rt_library "-lgcc")
endfunction()

message(STATUS "Xtensa LLVM: triple=${triple} mcpu=${XTENSA_CLANG_MCPU}")
message(STATUS "Xtensa LLVM: CROSS_COMPILE=${CROSS_COMPILE}")
message(STATUS "Xtensa LLVM: GNULD_LINKER=${GNULD_LINKER}")

# .S assembly files need the GCC assembler for Xtensa-specific instructions
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -fno-integrated-as -fno-unwind-tables" CACHE STRING "" FORCE)


# LLEXT shared libraries are loadable modules, not standalone executables.
# Prevent the GCC driver from linking crt0.o/crtn.o into them.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostartfiles -nodefaultlibs" CACHE STRING "" FORCE)

# Override the shared library link rule with our wrapper script that:
# 1. Uses objcopy to make .rodata sections writable (fixes "dangerous
# relocation in read-only section")
# 2. Links with GCC + -mtext-section-literals (fixes "l32r literal placed
# after use" errors from section ordering)
set(LLEXT_LINK_WRAPPER "${CMAKE_CURRENT_LIST_DIR}/llext-link-wrapper.sh")
set(XTENSA_CROSS_PREFIX "$ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-")
set(CMAKE_C_CREATE_SHARED_LIBRARY
"${LLEXT_LINK_WRAPPER} ${XTENSA_CROSS_PREFIX} <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" CACHE STRING "" FORCE)
set(CMAKE_CXX_CREATE_SHARED_LIBRARY
"${LLEXT_LINK_WRAPPER} ${XTENSA_CROSS_PREFIX} <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" CACHE STRING "" FORCE)
set(CMAKE_C_CREATE_SHARED_MODULE
"${LLEXT_LINK_WRAPPER} ${XTENSA_CROSS_PREFIX} <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_C_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" CACHE STRING "" FORCE)
set(CMAKE_CXX_CREATE_SHARED_MODULE
"${LLEXT_LINK_WRAPPER} ${XTENSA_CROSS_PREFIX} <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" CACHE STRING "" FORCE)
# Set XTENSA_GCC for use by toolchain_linker_finalize() in
# cmake/linker/ld/target.cmake — clang can't drive the Xtensa linker
# because it falls back to /usr/bin/ld which doesn't understand Xtensa ELF.
set(XTENSA_GCC $ENV{ZEPHYR_SDK_INSTALL_DIR}/gnu/${CROSS_COMPILE_TARGET}/bin/${CROSS_COMPILE_TARGET}-gcc)

# Also set CMAKE_C/CXX_LINK_EXECUTABLE early so LLEXT targets (which are
# created via add_executable before toolchain_linker_finalize runs) inherit
# the correct linker. toolchain_linker_finalize will override these again
# for the main firmware with the proper std lib ordering.
set(CMAKE_C_LINK_EXECUTABLE
"${XTENSA_GCC} <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" CACHE STRING "" FORCE)
set(CMAKE_CXX_LINK_EXECUTABLE
"${XTENSA_GCC} <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" CACHE STRING "" FORCE)

# Disable ccache for link steps — ccache can't properly handle our
# wrapper script (it caches/eats the output).
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "")
endif()

if(DEFINED triple)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_ASM_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER_TARGET ${triple})

unset(triple)
endif()

if(NOT "${ARCH}" STREQUAL "xtensa")
if(CONFIG_LIBGCC_RTLIB)
set(runtime_lib "libgcc")
elseif(CONFIG_COMPILER_RT_RTLIB)
set(runtime_lib "compiler_rt")
endif()

if(DEFINED runtime_lib)
list(APPEND TOOLCHAIN_C_FLAGS --config=${ZEPHYR_BASE}/cmake/toolchain/llvm/clang_${runtime_lib}.cfg)
list(APPEND TOOLCHAIN_LD_FLAGS --config=${ZEPHYR_BASE}/cmake/toolchain/llvm/clang_${runtime_lib}.cfg)
endif()
endif()
4 changes: 3 additions & 1 deletion include/zephyr/sys/cbprintf.h
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@
* @return the number of characters generated, or a negative error value
* returned from invoking @p out.
*/
#ifdef CONFIG_PICOLIBC
// FIXME: libc.a from Zephyr SDK needs built with clang if clang used to build zephyr

Check failure on line 733 in include/zephyr/sys/cbprintf.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

include/zephyr/sys/cbprintf.h:733 do not use C99 // comments See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details.

Check warning on line 733 in include/zephyr/sys/cbprintf.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

include/zephyr/sys/cbprintf.h:733 please, no spaces at the start of a line See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details.

Check failure on line 733 in include/zephyr/sys/cbprintf.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

TRAILING_WHITESPACE

include/zephyr/sys/cbprintf.h:733 trailing whitespace See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details.

Check warning on line 733 in include/zephyr/sys/cbprintf.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Take the required action to fix the issue indicated by this "FIXME" comment.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZ4IzJ_Ui2zGCx4xITuy&open=AZ4IzJ_Ui2zGCx4xITuy&pullRequest=108765

Check warning on line 733 in include/zephyr/sys/cbprintf.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Convert this C99/C++ (// ...) style comment into a C90 (/* ... */) one.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZ4IzJ_Ui2zGCx4xITux&open=AZ4IzJ_Ui2zGCx4xITux&pullRequest=108765
#if defined(CONFIG_PICOLIBC) && !defined(__clang__)
int cbvprintf(cbprintf_cb out, void *ctx, const char *format, va_list ap);
#else
static inline
Expand All @@ -740,6 +741,7 @@
}
#endif


/** @brief varargs-aware *printf-like output through a callback with tagged arguments.
*
* This is essentially vsprintf() except the output is generated
Expand Down
22 changes: 22 additions & 0 deletions lib/libc/picolibc/cbprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@

#include "picolibc-hooks.h"

/*
* When using Clang with a GCC-compiled picolibc (e.g. from the Zephyr SDK),
* the va_list ABI may not be compatible across the Clang→GCC boundary on
* Xtensa windowed targets. Routing through picolibc's vfprintf causes crashes
* because the GCC-compiled __d_vfprintf misinterprets the Clang-constructed
* va_list.
*
* To avoid this, use Zephyr's own cbvprintf_complete/cbvprintf_nano
* (compiled by the same compiler as the caller) as the formatting engine.
* Picolibc is still used for headers (math.h, stdio.h) and libm.
*/
#if defined(__clang__)

/* Use Zephyr's native cbprintf implementation.
* cbvprintf is defined as a weak alias in cbprintf_complete.c / cbprintf_nano.c
* and will be linked from there. We simply don't provide our own.
*/

#else /* GCC - original picolibc path */

struct cb_bits {
FILE f;
cbprintf_cb out;
Expand All @@ -29,3 +49,5 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap)
};
return vfprintf(&s.f, fp, ap);
}

#endif /* __clang__ */
Loading
Loading