Summary
This is a proposal to introduce a new clang command line option --libc to specify the standard C library to use.
Background
There are multiple standard C libraries available to use, especially in the embedded space. Today there is a way to chose which C++ library to use (LLVM libc++ or GCC libstdc++) as well as Glibc or MuslC for a Linux target, however there is no standard/dedicated way to select a C library in the bare-metal driver.
Related discussion in LLVM libc monthly: Monthly LLVM libc meeting - #36 by michaelrj-google
Related existing options:
-nolibc
-stdlib=<arg>, --stdlib=<arg>, --stdlib <arg>
C++ standard library to use. <arg> must be âlibc++â, âlibstdc++â or âplatformâ.
Goal
Provide a standard way to select C library to use for embedded use cases.
Out of Scope
Hosted use cases like glibc vs muslc on Linux (<arch>-linux-gnu and <arch>-linux-musl target triples).
Proposal
Add a new command line option --libc in the scope of the BareMetal driver:
-libc=<arg>, --libc=<arg>, --libc <arg>
C standard library to use. <arg> can be any string, âsystemâ is the default.
Provide CLANG_DEFAULT_C_LIB, similar to CLANG_DEFAULT_CXX_STDLIB, to override the default C library.
Initially, make the string provided to --libc available to the multilib selection logic only and let multilib handle it - no hardcoded logic in the driver. Later, either generic or library specific logic can be added in the library handling or even library specific optimizations in the compiler - each of these require careful analysis and design on its own.
Note: Strings used for --libc should be aligned with RUNTIMES_USE_LIBC option used for libc++, today only system and llvm-libc are supported in HandleLibC.cmake, however there is an open pull request to add picolibc and newlib.
Benefits
- Standard option to specify C library to use, aligned with that for standard C++ library to use and building without C library.
- Keeping list of library names open ended provides minimum implementation and maximum flexibility in regards to forward compatibility as it does not prescribe any driver behavior - it is kept in the multilib logic.
Implementation
- Add build time CMake option
CLANG_DEFAULT_C_LIBso that toolchains can choose. - Add
--libcoption in Options.td - Pass the value provided for
--libcoption to multilib backend in ToolChain.cpp - Make use of the value provided for
--libcoption in building the path tomultilib.yamlfile in BareMetal.cpp driver. Thesystemoption is not added to the path, i.e does not change the current behavior.
NOTE: Drivers that do not usemultilib.yamlconfiguration (use custom logic in the driver) will not be affected by this change.
The rest of the library logic should be handled by the multilib, e.g. Arm Toolchain can use picolibc, llvmlibc, newlib and newlib-nano all just by pointing --sysroot to the correct multilib.yaml file via a config file. Config file adds the benefit of using a macro to get the root folder of the toolchain to create a relative path to the yaml file - otherwise the full absolute path has to be provided to --sysroot, which is not practical.
Arm Toolchain example: path to multilib.yaml is set in getMultilibConfigPath() by appending yaml file name to ClangRuntimesSysRoot here. The default sysroot points to lib/clang-runtimes/ under the toolchain root, thus the default yaml file path is /lib/clang-runtimes/multilib.yaml
If the LLVM libc overlay package is used, then âconfig=llvmlibc.cfg overrides sysroot to lib/clang-runtimes/llvmlibc/ under the toolchain root, thus the resulting path is lib/clang-runtimes/llvmlibc/multilib.yaml
With the proposed change, the name of the library, llvmlibc in the example, should be appended to the sysroot in getMultilibConfigPath() (unless the specified library name is system to keep current bevahior) to get the same resulting lib/clang-runtimes/llvmlibc/multilib.yaml
NOTE: This change does not impact -stdlib handling: -stdlib=libstdc++ is not supported in the BareMetal driver for Arm targets.
Alternatives
- ATfE now uses config files to set the
--sysroot, e.g. llvmlibc.cfg. The drawback is that it is too generic and requires adding--config=llvmlib.cfgon the command line which can mean anything. - Provide a predefined list of libraries to support, analyze and generalize the driver logic required to support them all, implement required logic in the driver itself. A lot of upfront work and alignment, likely difficult to extend later when a new library appears that has incompatible assumptions about use.
- Use target triples like
arm-none-picolibceabiandarm-none-llvmlibceabisimilar toaarch64-linux-musl,aarch64-linux-androidandaarch64-linux-gnu- this has the drawback of predefined list of supported libraries and is not really related to the ABI.