Skip to content
36 changes: 36 additions & 0 deletions cmake/compiler/clang/target.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,42 @@ if(NOT "${ARCH}" STREQUAL "posix")
endif()
endif()

# LLVM will use a default sysroot for selection of the C library. The default
# C library sysroot was defined at built time of clang/LLVM.
#
# For example, LLVM for Arm comes pre-built with Picolibc, and thus no flags
# are required for selecting Picolibc.
#
# Other clang/LLVM distributions may come with other pre-built C libraries.
# clang/LLVM supports using an alternative C library, either by direct linking,
# or by specifying '--sysroot <path>'.
#
# LLVM for Arm provides a 'newlib.cfg' file for newlib C selection.
# Let us support this principle by looking for a dedicated 'newlib.cfg' or
# 'picolibc.cfg' and specify '--config <spec>.cfg' if such a file is found.
# If no cfg-file matching the chosen C implementation, then we assume that the
# chosen C implementation is identical to the default C library used be the
# toolchain.
if(CONFIG_NEWLIB_LIBC)
file(GLOB_RECURSE newlib_cfg ${LLVM_TOOLCHAIN_PATH}/newlib.cfg)
if(newlib_cfg)
list(GET newlib_cfg 0 newlib_cfg)
set_linker_property(PROPERTY c_library "--config=${newlib_cfg};-lc")
list(APPEND CMAKE_REQUIRED_FLAGS --config=${newlib_cfg})
list(APPEND TOOLCHAIN_C_FLAGS --config=${newlib_cfg})
endif()
endif()

if(CONFIG_PICOLIBC)
file(GLOB_RECURSE picolibc_cfg ${LLVM_TOOLCHAIN_PATH}/picolibc.cfg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe share the --specs mechanism somehow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see other answer related to this. But good to have in mind for further improvements 👍

if(picolibc_cfg)
list(GET picolibc_cfg 0 picolibc_cfg)
set_linker_property(PROPERTY c_library "--config=${picolibc_cfg};-lc")
list(APPEND CMAKE_REQUIRED_FLAGS --config=${picolibc_cfg})
list(APPEND TOOLCHAIN_C_FLAGS --config=${picolibc_cfg})
endif()
endif()

# This libgcc code is partially duplicated in compiler/*/target.cmake
execute_process(
COMMAND ${CMAKE_C_COMPILER} ${clang_target_flag} ${TOOLCHAIN_C_FLAGS}
Expand Down
24 changes: 23 additions & 1 deletion cmake/toolchain/llvm/generic.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,28 @@ set(LLVM_TOOLCHAIN_PATH ${CLANG_ROOT_DIR} CACHE PATH "clang install directory")
set(COMPILER clang)
set(BINTOOLS llvm)

set(TOOLCHAIN_HAS_NEWLIB OFF CACHE BOOL "True if toolchain supports newlib")
# LLVM is flexible, meaning that it can in principle always support newlib or picolibc.
# This is not decided by LLVM itself, but depends on libraries distributed with the installation.
# Also newlib or picolibc may be created as add-ons. Thus always stating that LLVM does not have
# newlib or picolibc would be wrong. Same with stating that LLVM has newlib or Picolibc.
# The best assumption for TOOLCHAIN_HAS_<NEWLIB|PICOLIBC> is to check for the presence of
# '_newlib_version.h' / 'picolibc' and have the default value set accordingly.
# This provides a best effort mechanism to allow developers to have the newlib C / Picolibc library
# selection available in Kconfig.
# Developers can manually indicate library support with '-DTOOLCHAIN_HAS_<NEWLIB|PICOLIBC>=<ON|OFF>'

# Support for newlib is indicated by the presence of '_newlib_version.h' in the toolchain path.
if(NOT LLVM_TOOLCHAIN_PATH STREQUAL "")
file(GLOB_RECURSE newlib_header ${LLVM_TOOLCHAIN_PATH}/_newlib_version.h)
if(newlib_header)
set(TOOLCHAIN_HAS_NEWLIB ON CACHE BOOL "True if toolchain supports newlib")
endif()

# Support for picolibc is indicated by the presence of 'picolibc.h' in the toolchain path.
file(GLOB_RECURSE picolibc_header ${LLVM_TOOLCHAIN_PATH}/picolibc.h)
if(picolibc_header)
set(TOOLCHAIN_HAS_PICOLIBC ON CACHE BOOL "True if toolchain supports picolibc")
endif()
endif()

message(STATUS "Found toolchain: llvm (clang/ld)")