ChromeOS provides a baremetal LLVM toolchain that can be used to build both EC and Zephyr. The EC and Zephyr-based fingerprint firmware use the LLVM toolchain by default. This document provides details on how the toolchain is configured and built.
riscv32-cros-elfarmv7m-cros-eabiarm-none-eabicros_setup_toolchains is the script used to build the various ChromeOS toolchains. It‘s a wrapper around Gentoo’s crossdev, which is a script to configure and build the necessary components for a cross-compiler toolchain. One area where cros_setup_toolchains diverges from crossdev is in its handling of LLVM-based toolchains. crossdev has LLVM toolchain support, but cros_setup_toolchains does not use it. Instead, cros_setup_toolchains adds extra LLVM packages to the crossdev commandline.
Ultimately, cros_setup_toolchains invokes crossdev with a set of flags. You can see the exact crossdev command invoked in the output:
(chroot) sudo `which cros_setup_toolchains` -t riscv32-cros-elf --nousepkg
16:29:01.241: INFO: run: crossdev --stable --show-fail-log --env 'FEATURES=splitdebug' -P --oneshot --overlays '/mnt/host/source/src/third_party/chromiumos-overlay /mnt/host/source/src/third_party/eclass-overlay /mnt/host/source/src/third_party/portage-stable' --ov-output /usr/local/portage/crossdev -t riscv32-cros-elf --ex-pkg sys-libs/compiler-rt --ex-pkg sys-libs/llvm-libunwind --ex-pkg sys-libs/libcxx --binutils '[stable]' --gcc '[stable]' --libc '[stable]' --ex-gdb
The packages that make up the toolchain are defined in the toolchain overlay. crossdev searches for ebuilds in the directory cross-<target-triple>, where <target-triple> has this definition.
As an example, if you want to build a toolchain with the triple riscv32-cros-elf, you would run:
(chroot) sudo `which cros_setup_toolchains` -t riscv32-cros-elf --nousepkg
which will ultimately result in a call to crossdev, which will search for ebuilds in chromiumos/overlays/toolchains/cross-riscv32-elf. That directory simply contains symlinks to the canonical ChromeOS ebuild for the package. See https://crrev.com/c/6349977 for an example.
In the toolchain overlay for our baremetal toolchains, you'll see the following components:
binutils: GNU Binutilscompiler-rt: Compiler Runtime libraries for LLVM and clang.gcc: should not be needed for an LLVM toolchain, but crossdev assumes that you need a minimal stage1 gcc and builds it anyway.gdb: The GNU Project Debugger.libcxx: libc++ C++ standard libraryllvm-libunwind: libunwind LLVM Unwindernewlib: The newlib C standard library is an implementation of the C standard library targeting embedded systems.Once you‘ve successfully built a toolchain with cros_setup_toolchains or you’re using a chroot that has an SDK with a prebuilt toolchain, you can use emerge to rebuild the individual components as you make changes to the associated ebuild.
If you are making changes to a -9999 ebuild, you‘ll need to use cros-workon --host. In addition, for the ebuilds that use the LLVM source, you’ll need to sync the LLVM source by adding the toolchain group, since it's marked as notdefault in the repo manifest:
(outside) repo init -g toolchain,default
For example, if you change some compiler flags in the compiler-rt ebuild, and want to rebuild it for RISC-V, you would do:
(chroot) cros-workon --host start cross-riscv32-cros-elf/compiler-rt (chroot) emerge cross-riscv32-cros-elf/compiler-rt
The standard Portage equery commands work on these packages as well, so you can do things like:
List the files in a package:
(chroot)$ equery files <package>
(chroot) equery files cross-riscv32-cros-elf/compiler-rt * Searching for compiler-rt in cross-riscv32-cros-elf ... * Contents of cross-riscv32-cros-elf/compiler-rt-20.0_pre547379-r48: /usr /usr/lib64 /usr/lib64/clang /usr/lib64/clang/20 /usr/lib64/clang/20/lib /usr/lib64/clang/20/lib/baremetal /usr/lib64/clang/20/lib/baremetal/libclang_rt.builtins-riscv32.a
Find the package that provides a file:
(chroot) equery belongs /path/to/file
(chroot) equery belongs /usr/lib64/clang/20/lib/baremetal/libclang_rt.builtins-riscv32.a cross-riscv32-cros-elf/compiler-rt-20.0_pre547379-r48 (/usr/lib64/clang/20/lib/baremetal/libclang_rt.builtins-riscv32.a)
When modifying an ebuild for a component in the baremetal toolchain, you'll want to make sure that the EC and Zephyr builds succeed, in addition to the Renode tests passing. You can do that by adding the following to the commit message:
Cq-Include-Trybots: chromeos/cq:firmware-ec-cq,firmware-zephyr-cq,firmware-ec-renode-cq
Automating this is tracked in http://b/406868085.
If you want to add a baremetal toolchain for a new target triple, see the CLs created for creating the RISC-V toolchain.
The general flow is:
toolchain.conf file in an existing overlay.cros_setup_toolchains.is_baremetal_abi.is_baremetal_abi to configure target-specific compilation flags.