-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fe310: Support compilation with clang #15176
Conversation
This requires -nostartfiles to be only passed to the linker, not the compiler, as it is a linker flag and passing it to the compiler causes a clang warning to be emitted. Additionally, clang does not seem to support `-mcmodel=medlow` and `-msmall-data-limit=8` but these options do not seem strictly necessary to me anyhow thus they are deactivated conditionally when using clang.
read_csr() returns an unsigned long, not a uint32_t. This causes a -Wformat warning to be emitted when compiling with clang. This commit fixes the warning by changing the format string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, but I don't have the hardware to test.
Output binary does not change with gcc though, so this should be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you detail how you build for hifive1(b) ?
I tried the following but it's failing:
$ BUILD_IN_DOCKER=1 TOOLCHAIN=llvm make BOARD=hifive1b -C examples/default/ flash term
make: Entering directory '/work/riot/RIOT/examples/default'
Falling back to legacy riscv-none-embed toolchain
Launching build container using image "riot/riotbuild:latest".
docker run --rm --tty --user $(id -u) -v '/usr/share/zoneinfo/Europe/Paris:/etc/localtime:ro' -v '/work/riot/RIOT:/data/riotbuild/riotbase:delegated' -e 'RIOTBASE=/data/riotbuild/riotbase' -e 'CCACHE_BASEDIR=/data/riotbuild/riotbase' -e 'BUILD_DIR=/data/riotbuild/riotbase/build' -e 'RIOTPROJECT=/data/riotbuild/riotbase' -e 'RIOTCPU=/data/riotbuild/riotbase/cpu' -e 'RIOTBOARD=/data/riotbuild/riotbase/boards' -e 'RIOTMAKE=/data/riotbuild/riotbase/makefiles' -e 'BOARD=hifive1b' -e 'TOOLCHAIN=llvm' -w '/data/riotbuild/riotbase/examples/default/' 'riot/riotbuild:latest' make 'BOARD=hifive1b'
Falling back to legacy riscv-none-embed toolchain
Building application "default" for "hifive1b" with MCU "fe310".
clang: error: argument unused during compilation: '-march=rv32imac' [-Werror,-Wunused-command-line-argument]
clang: error: argument unused during compilation: '-mabi=ilp32' [-Werror,-Wunused-command-line-argument]
/data/riotbuild/riotbase/Makefile.base:107: recipe for target '/data/riotbuild/riotbase/examples/default/bin/hifive1b/application_default/main.o' failed
make[1]: *** [/data/riotbuild/riotbase/examples/default/bin/hifive1b/application_default/main.o] Error 1
/data/riotbuild/riotbase/Makefile.include:603: recipe for target 'application_default.module' failed
That is more or less the command I am also using. I don't use the RIOT docker image though, looking at the error it seems to me that the clang version in the docker image doesn't have RV32 support? Can you check if |
Thanks @nmeum. Indeed riscv32 is not available in the Docker image. So I tried with my local llvm where it's there. But the build is still failing:
Then I tried to override
|
The RIOT/makefiles/toolchain/llvm.inc.mk Lines 15 to 20 in 080d5ca
|
All this should be documented somewhere, otherwise it's pretty useless for other people who don't necessarily know how to set this up (like me :) ). |
Right, I agree. However, this is by no means RISC-V specific. Most RIOT platforms I used so far require newlib to be installed, that's really independent of the utilized C compiler (i.e. not specific to the LLVM toolchain). |
Is there something blocking this still? |
I still have an unaddressed comment. Did you try that PR @benpicco ?
Yes I have a local toolchain for riscv but it's not in a system directory. I would be nice if the build system could handle this location based on the |
Which one? The one regarding documentation? I agree that clang documentation should be improved but I don't think that this is specific to this PR and maybe could be addressed separately?
Could you elaborate what you mean by that?
Because that's the target triplet of the toolchain you have installed while RIOT defaults to the triplet RIOT/makefiles/arch/riscv.inc.mk Line 2 in d9e495f
I honestly think that CC: @maribu |
If you need the newlib from the riscv toolchain, I think it would help to add the corresponding includes in the build. Maybe this could be done by the RIOT build system when using the llvm toolchain and will automate things for the user. For my error above, the
So I'm just wondering if adding |
Missed that, sorry! Applied your suggestion now. Should I squash it too?
The LLVM Makefile extracts include directories from the utilized GCC, (i.e. RIOT/makefiles/toolchain/llvm.inc.mk Lines 66 to 71 in 080d5ca
That seems to work for me. Maybe debug this part of the Makefile to figure out why it doesn't work for you? RIOT/makefiles/toolchain/llvm.inc.mk Lines 45 to 51 in 080d5ca
|
File a bug there ;-) From https://clang.llvm.org/docs/CrossCompilation.html#target-triple
As |
I think I'm starting to understand but things are still a bit unclear to me :)
No I think it works because llvm accepts this triplet (as mentioned by @maribu). But my local triplet is So with the current default RIOT toolchain setup (the one in Docker which is also |
Ah! That make sense because the triplet is passed to clang too using the RIOT/makefiles/toolchain/llvm.inc.mk Lines 58 to 60 in 080d5ca
Do you get an error message from clang with
Not sure if I missing something here, but if this is just about the triplet name I would rather vouch for adjusting the default RIOT RISC-V triplet to make it work by with clang if clang does not support the |
Yes:
That could be an option but that would need an update of riotdocker. |
@maribu Could you briefly explain what you mean by that? I started using the Alpine packed If I make the following changes to the build system, compilation with clang works fine again: diff --git a/makefiles/toolchain/llvm.inc.mk b/makefiles/toolchain/llvm.inc.mk
index 9898f10f8..182d71ee6 100644
--- a/makefiles/toolchain/llvm.inc.mk
+++ b/makefiles/toolchain/llvm.inc.mk
@@ -56,8 +56,8 @@ ifneq (,$(TARGET_ARCH))
endif
# Tell clang to cross compile
- CFLAGS += -target $(TARGET_ARCH)
- CXXFLAGS += -target $(TARGET_ARCH)
+ CFLAGS += -target riscv32-unknown-elf
+ CXXFLAGS += -target riscv32-unknown-elf
# We currently don't use LLVM for linking (see comment above).
# LINKFLAGS += -target $(TARGET_ARCH) So why does the RIOT docker image and the Alpine package use a triplet which is not supported by clang? If RIOT (and Alpine) just default to |
@nmeum: I can also reproduce the issue. I don't think there is a need to have the GCC target triple and the clang target triple identical, e.g. the legacy toolchain with However: I suggest to use The reason that for GCC I chose |
I would personally want to avoid introducing yet another Makefile variable for configuring the compilation target, just makes the current setup even more complicated IMHO.
Fine with me, if the former is supported by clang too.
I doubt that anyone sees through the semantic meaning of these triplets. I would personally just stick to what is used elsewhere, for instance in https://github.com/riscv/riscv-gnu-toolchain. |
Thanks for the heads up, rebased against |
Maybe better to fix this separately, changing the type might require changes elsewhere in the code base too. |
Fully agree, don't want to make this PR bigger than it has to be, just wanted to have your opinion on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
@aabadie: Can you have a look here? |
Now I end up with another build failure:
What is supposed to be done to get a successful build with clang ? Anyone else tried ? |
Sorry for joining in that late into the discussion, but should we maybe add an Line 7 in d7f3e92
so once gets merged we also compile test the LLVM config? |
|
Oh sorry, just looked at the title and the code, but not the discussion ^^" |
This is a regression, My local rebuild of all toolchains is still ongoing, so I cannot test (due to missing c lib). But I think this should fix the issue: diff --git a/makefiles/arch/riscv.inc.mk b/makefiles/arch/riscv.inc.mk
index 354a920b38..02c79613e9 100644
--- a/makefiles/arch/riscv.inc.mk
+++ b/makefiles/arch/riscv.inc.mk
@@ -35,10 +35,12 @@ ifeq ($(TOOLCHAIN),llvm)
# Always use riscv32-none-elf as target triple for clang, as some
# autodetected gcc target triples are incompatible with clang
TARGET_ARCH := riscv32-none-elf
+ CFLAGS_LINK :=
else
CFLAGS_CPU += -mcmodel=medlow -msmall-data-limit=8
+ CFLAGS_LINK := -nostartfiles
endif
-CFLAGS_LINK = -nostartfiles -ffunction-sections -fdata-sections
+CFLAGS_LINK += -ffunction-sections -fdata-sections
CFLAGS_DBG ?= -g3
CFLAGS_OPT ?= -Os |
Oops, I think I made a minor mistake during rebasing today. Might have not properly rebuild my test application. Will check tomorrow, sorry for the inconvenience. |
Maybe you could also enable Murdock compilation of the |
Not too familiar with murdock but I will look into it. |
I doubt that will work right away on Murdock. If I build in Docker, I get this:
And I have the same issue when using my local toolchain (and after applying your patch above). |
see #15176 (comment) |
I just remembered that |
Fixed the problem with RIOT/makefiles/toolchain/llvm.inc.mk Lines 45 to 51 in 080d5ca
For the record, Lines 344 to 346 in d1deb6f
I already laid out my preferred way to fix the triplet mismatch problems in #15176 (comment). Unfortunately, another problem appread with the merge of #15011: the picolib version my RISC-V cross toolchain is using does not work with clang presently. tl;dr This requires a recent picolib version and the triplet mismatch issue needs a different fix I guess. |
087ac0d
to
5b15dc8
Compare
Rebased. The following command:
works for me again now with clang10. Thanks @maribu! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK. (And this time I double checked that no regressions have popped up due to upstream changes)
Now you don't even need to add in Docker (my image uses https://github.com/RIOT-OS/riotdocker/pull/131):
on the host (Ubuntu):
|
ifeq ($(TOOLCHAIN),llvm) | ||
# Always use riscv32-none-elf as target triple for clang, as some | ||
# autodetected gcc target triples are incompatible with clang | ||
TARGET_ARCH_LLVM := riscv32-none-elf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TARGET_ARCH_LLVM := riscv32-none-elf | |
TARGET_ARCH_LLVM ?= riscv32-none-elf |
With this, you can override this value with a different triple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This flexibility is luckily not needed for LLVM. Technically, riscv32-none-elf
is the correct target triplet for 32 bit embedded (bare metal) RISC-V targets. Differently to GCC, the target triplet is just an argument rather than a prefix to the binaries and managed upstream, so unless one manually patches clang to only work with incorrect target triples, nobody will need to change this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of the riscv64-none-elf triplet available in the Debian/Ubuntu package manager. On Debian/Ubuntu, that would need picolibc but IIUC, it might be possible to use llvm also with picolibc ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of the riscv64-none-elf triplet available in the Debian/Ubuntu package manager.
No, the libraries are resolved using the triple in TARGET_ARCH
, which can be distinct from TARGET_ARCH_LLVM
. The issue is that riscv64-none-elf
is the correct triple for the 64 bit RISC-V, but we only support 32 bit so far. A riscv64-none-elf
multilib GCC toolchain would support both 32 and 64 bit flavors, but clang
wants the correct triple.
E.g. when the c lib is installed as riscv-none-embed
, this is a completely invalid target triple. But splitting the target triple used to resolve the GCC toolchain and c library from the target triple passed to LLVM, we overcome the issues.
IIUC, it might be possible to use llvm also with picolibc ?
Yes, starting with clang11
it is possible. clang10
doesn't understand the -specs=
parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarifications @maribu. Makes sense to me now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My latest tests were successful and the code changes look good to me.
ACK
Contribution description
Not sure if there is any interested in this but I am personally currently working on using the HiFive1 with the clang compiler. The changes below enabled me to do so, currently doing some more manual testing but haven't found any issues so far. 91707a6 might be useful even if you are not interested in supporting the clang/llvm toolchain on the hifive1.
Testing procedure
Compile some example applications with
BOARD=hifive1
and run them.Issues/PRs references
None.