zephyrproject-rtos / sdk-ng

Zephyr SDK (Toolchains, Development Tools)
Apache License 2.0
185 stars 134 forks source link

Clang/LLVM Toolchain Support #777

Open stephanosio opened 2 months ago

stephanosio commented 2 months ago

This enhancement issue describes the Clang/LLVM toolchain support plan in the Zephyr SDK.

Goals

Specifications

[1] Based on the "LLVM Binary Utilities" included in LLVM Embedded Toolchain for Arm. [2] Based on the pre-built multi-libs included in LLVM Embedded Toolchain for Arm. [3] Based on the pre-built 32-bit RISC-V multi-libs currently included in the SDK GCC. [4] LLVM Linker (lld) support is currently very limited and it is desirable to use GNU Linker (ld) for maximum compatibility. Note that GNU Linker is used by default for ZEPHYR_TOOLCHAIN_VARIANT=llvm as well. lld support seems to be sufficiently mature now. [5] This ensures that GNU Linker, which is part of GNU Binutils, can be installed alongside Clang/LLVM toolchain without installing GCC. [6] Ideally, we would implement Clang/LLVM toolchain support in crosstool-ng and upstream it; but, doing so will likely delay this task too much for our liking -- we will see.

Tasks

Phase 1

Inclusion of Clang/LLVM toolchain binaries and pre-built compiler-rt library for Arm-M-profile cores and RISC-V RV32I and RV32E cores in the SDK

Phase 2

Addition of pre-built C/C++ libraries for Arm M-profile cores and RISC-V RV32I and RV32E cores to the SDK

Future

(Nothing concrete about these ...)

Resources

stephanosio commented 2 months ago

FYI @carlescufi @tejlmand

dkalowsk commented 2 months ago

@stephanosio are there expected to be Zephyr specific changes to the LLVM build? If so, would it make sense to include libclang to allow developers to build extensions on it?

stephanosio commented 2 months ago

@stephanosio are there expected to be Zephyr specific changes to the LLVM build?

Not right now; but, it is foreseeable that we will need to carry some local patches in the future.

If so, would it make sense to include libclang to allow developers to build extensions on it?

That is an interesting topic -- if it does not add too much to the build time or the distribution archive size, I think libclang would be a reasonable addition.

carlescufi commented 2 months ago

Architecture WG:

jonathonpenix commented 2 months ago

I'm super excited to see this--thank you @stephanosio for creating this! This looks great to me, though I do have a few questions I'm hoping to run by you:

  1. Could we consider including AArch64 support as part of this (at least a very basic config similar to what is included in the LLVM Embedded Toolchain for Arm)? As best I understand, all the Arm library variants listed above are 32bit. AArch64 is well supported in LLVM and Zephyr has some baseline support for LLVM + AArch64 as well.
  2. Are you targeting a particular version of LLVM to start with? I think 18 is the most recent official release, but LLVM has branched 19.1.0-rc4 and I think is getting close to branching 19.1.0-final--so, 19 might be an option soon as well. When I've tested locally, I have seen a few issues that were fixed in LLVM's mainline/later releases--it likely isn't a huge deal either way, but might be something to keep in mind.
  3. Related to 2 above, LLVM's multilib support might also be a challenge here. LLVM's YAML solution was added for baremetal Arm/AArch64 a few releases ago (and is still seeing active changes) but this was only very recently extended to RISC-V (https://github.com/llvm/llvm-project/commit/b221c37082707e35b492baa9ae8045c56b3ced0b, ~1 month ago)--I don't think robust multilib support will be in place in LLVM for RISC-V unless we use a mainline build of LLVM or we wait for the next release. Historically, there was only very minimal hard-coded RISC-V "multilib support" (see here in the 19 release sources, for example). So, if LLVM <= 19 is used to start with, maybe it would be worth including only a minimal subset of the RISC-V library variants to begin with and expanding this later when we have access to better multilib capabilities?
  4. Related to "A custom build script shall be implemented for building Clang/LLVM toolchain" and "Implement Clang/LLVM toolchain support in crosstool-ng and refactor the SDK build process to use it": I know you mentioned that this isn't concrete (and I'm not familiar with crosstool-ng so I'm not sure how much work this would be or if there is any LLVM support already in place), but IIRC one thing that was mentioned in one of the recent LLVM RISC-V or Embedded toolchain meetings was whether there'd be any interest in essentially an "LLVM Embedded Toolchain for Arm" but extended to support building for RISC-V as well. Would this be something that you/Zephyr would be interested in using to build the toolchain? Or, is crosstool-ng (or other scripts, etc.) preferred long-term? If you/Zephyr would be interested, I'd be interested in discussing more and looping in a few LLVM folks!
stephanosio commented 2 months ago

1. Could we consider including AArch64 support as part of this (at least a very basic config similar to what is included in the LLVM Embedded Toolchain for Arm)? As best I understand, all the Arm library variants listed above are 32bit. AArch64 is well supported in LLVM and Zephyr has some baseline support for LLVM + AArch64 as well.

Yes, I am planning to also include the AArch64 support if there is no major obstacle in doing so (AFAICS, there should be none).

2. Are you targeting a particular version of LLVM to start with? I think 18 is the most recent official release, but LLVM has branched 19.1.0-rc4 and I think is getting close to branching 19.1.0-final--so, 19 might be an option soon as well. When I've tested locally, I have seen a few issues that were fixed in LLVM's mainline/later releases--it likely isn't a huge deal either way, but might be something to keep in mind.

I am planning to start with LLVM 18 for now, mainly because that is what the latest release of LLVM Embeeded Toolchain for Arm has and I will be implementing the SDK build script based on that.

3. Related to 2 above, LLVM's multilib support might also be a challenge here. LLVM's YAML solution was added for baremetal Arm/AArch64 a few releases ago (and is still seeing active changes) but this was only very recently extended to RISC-V (llvm/llvm-project@b221c37, ~1 month ago)--I don't think robust multilib support will be in place in LLVM for RISC-V unless we use a mainline build of LLVM or we wait for the next release. Historically, there was only very minimal hard-coded RISC-V "multilib support" (see here in the 19 release sources, for example). So, if LLVM <= 19 is used to start with, maybe it would be worth including only a minimal subset of the RISC-V library variants to begin with and expanding this later when we have access to better multilib capabilities?

At first glance, writing a patch to support the additional variants required by the Zephyr SDK (especially, the RV32E variants) looks like it should be fairly simple -- we can carry that patch in the Zephyr fork of LLVM until a new LLVM release with more robust RISC-V multi-lib support is available.

If that turns out to be not so simple for whatever reason, I will have to look into upgrading to a newer LLVM codebase or even brute-forcing the Zephyr build system to manually handle the RISC-V multi-lib variants ...

4. Related to "A custom build script shall be implemented for building Clang/LLVM toolchain" and "Implement Clang/LLVM toolchain support in crosstool-ng and refactor the SDK build process to use it": I know you mentioned that this isn't concrete (and I'm not familiar with crosstool-ng so I'm not sure how much work this would be or if there is any LLVM support already in place), but IIRC one thing that was mentioned in one of the recent LLVM RISC-V or Embedded toolchain meetings was whether there'd be any interest in essentially an "LLVM Embedded Toolchain for Arm" but extended to support building for RISC-V as well. Would this be something that you/Zephyr would be interested in using to build the toolchain? Or, is crosstool-ng (or other scripts, etc.) preferred long-term? If you/Zephyr would be interested, I'd be interested in discussing more and looping in a few LLVM folks!

crosstool-ng is a very popular tool for building embedded cross compiler toolchains, and that is what Zephyr SDK build system currently uses to build the GNU toolchains.

crosstool-ng is nice because it abstracts away all the tedious processes involved in building cross-compiler toolchains (e.g. builder OS -specific dependencies, host OS-specific dependencies, target dependencies ...) and allows one to build a toolchain from a Kconfig-based "recipe."

While it may not sound like much at first, it can be very useful when you are setting up a complex toolchain build environment such as one for a Canadian cross compiler (e.g. building aarch64-linux host toolchain from x86_64-linux build machine for riscv64-elf target).

While "LLVM Embedded Toolchain for RISC-V" that comes with custom scripts to build general purpose RISC-V LLVM toolchain sounds interesting, IMHO, having the ability to build any flavour of LLVM you want from a Kconfig-based recipe using crosstool-ng would be nicer.

jonathonpenix commented 2 months ago

Yes, I am planning to also include the AArch64 support if there is no major obstacle in doing so (AFAICS, there should be none).

Awesome! Apologies if I overlooked that somewhere.

I am planning to start with LLVM 18 for now, mainly because that is what the latest release of LLVM Embeeded Toolchain for Arm has and I will be implementing the SDK build script based on that.

Sounds good!

At first glance, writing a patch to support the additional variants required by the Zephyr SDK (especially, the RV32E variants) looks like it should be fairly simple -- we can carry that patch in the Zephyr fork of LLVM until a new LLVM release with more robust RISC-V multi-lib support is available.

If that turns out to be not so simple for whatever reason, I will have to look into upgrading to a newer LLVM codebase or even brute-forcing the Zephyr build system to manually handle the RISC-V multi-lib variants ...

Also sounds good! I think you're right that it should be fairly simple to add a patch to support additional variants but I also can't say I've tried it.

While "LLVM Embedded Toolchain for RISC-V" that comes with custom scripts to build general purpose RISC-V LLVM toolchain sounds interesting, IMHO, having the ability to build any flavour of LLVM you want from a Kconfig-based recipe using crosstool-ng would be nicer.

I see, makes sense! I don't have any particular objection here, it had just come up in LLVM's community a few times recently so I thought I would ask 🙂

Thank you again for proposing this and I'm excited to see this happen!

apazos commented 2 months ago

Great initiative, @stephanosio, to add on to @jonathonpenix's list, do you plan to include RISC-V 64 bit targets as well? Including Arm 32 and 64-bit targets, and RISC-V 32 and 64-bit targets will be useful. Also, any plans to also include hard float support?

keith-packard commented 1 month ago

I'm working on llvm toolchain support in picolibc by building with the LLVM embedded toolchain for Arm. I've found a few compatibility issues with clang and llvm-as, along with some differences in behavior between compiler-rt and libgcc (some look like bugs in compiler-rt to me). In any case, picolibc will be using that toolchain in CI going forward. Once there's a Zephyr clang toolchain, I'll add that to picolibc CI as well. https://github.com/picolibc/picolibc/pull/856

stephanosio commented 1 month ago

A preliminary test build from topic-clang branch is available with AArch64 and ARM (32-bit) multi-libs. No RISC-V multi-libs are available at this time.

To test, follow the steps below:

  1. Download https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.18.0-alpha1/zephyr-sdk-0.18.0-alpha1_linux-x86_64_llvm.tar.xz.
  2. Extract zephyr-sdk-0.18.0-alpha1_linux-x86_64_llvm.tar.xz.
  3. Run zephyr-sdk-0.18.0-alpha1/setup.sh -h.
  4. Set environment:
    export ZEPHYR_TOOLCHAIN_VARIANT=zephyr-llvm
    export ZEPHYR_SDK_INSTALL_DIR=/where-you-extracted/zephyr-sdk-0.18.0-alpha1
  5. Check out collab-sdk-0.18-dev branch.
  6. Build something.