Using Clang to compile for RISC-V

Foreknowledge:

I had same delusion about this: “If llvm is targeting for all backends including riscv, we should be able to compile our codes just giving a clang flag like --target=riscv32, -target riscv64 etc. without doing extra operation” and I had similar question, but it is not like that. Although LLVM supports riscv target, you need to specify sysroot and gcc toolchain for using riscv headers and libraries, in the other words you need cross compilation. (because you are currently operating a system like x86-64 different from riscv and your default libraries are different) That’s why you need to link your riscv-gnu-toolchain paths. Here I assume that you built your riscv-gnu-toolchain from github clone.

Note: Some people have problems with first option (1) and please try to use other options (2) (3) (4) firstly. (Look into comments.)

Solution:

1-) You can add these lines as your cmake configuration flags before building your llvm library:

For 32 bit riscv:

-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"

-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"

For 64 bit riscv:

-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"

-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"

and then build llvm library again. Probably as you know, in your llvm build directory:

cmake --build .

Here is an example in my case according to your cmake configuration for clearance:

cmake -G "Unix Makefiles" \
   -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests" \
   -DCMAKE_BUILD_TYPE=Debug \
   -DLLVM_ENABLE_ASSERTIONS=On \
   -DDEFAULT_SYSROOT="/home/shc/riscv/install/riscv64-unknown-elf" \
   -DGCC_INSTALL_PREFIX="/home/shc/riscv/install" \
   ../llvm

cmake --build .

Also you can set default target triple as riscv with another cmake configuration flag:

For 32 bit riscv:

-DLLVM_DEFAULT_TARGET_TRIPLE="riscv32-unknown-elf"

For 64 bit riscv:

-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf"

After this you should be able to compile your codes like these examples:

For C:

/home/shc/llvm/llvm-project/build/bin/clang -march=rv64gc hello_world.c -o hello_world

For C++:

/home/shc/llvm/llvm-project/build/bin/clang++ -march=rv64gc hello_world.cpp -o hello_world

If you didn’t set default target triple with cmake flag, target option should remain:

For C:

/home/shc/llvm/llvm-project/build/bin/clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world

For C++:

/home/shc/llvm/llvm-project/build/bin/clang++ --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world

2-) You can pass sysroot and gcc toolchain as flags(as in cmake configurations above) while compiling your code without building your library again. However, if you will use this, you need to give these flags in every compilation:

For 32 bit riscv:

--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"

--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"

For 64 bit riscv:

--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"

--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"

Usage of Flags For C:

/home/shc/llvm/llvm-project/build/bin/clang --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.c -o hello_world

Usage of Flags For C++:

/home/shc/llvm/llvm-project/build/bin/clang++ --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world

3-) You can try to pass these flags while compiling (instead of your --target=riscv64 flag) although it is not more healthy than above options. (Attention: difference is only linux keyword, normally it was -target riscv32-unknown-elf):

For 32 bit riscv:

-target riscv32-unknown-linux-elf

For 64 bit riscv:

-target riscv64-unknown-linux-elf

4-) You can use riscv-llvm repo by following given instructions, although it is outdated.

Note: I adapted my file locations to your examples to better understanding.

Further information you can look here: https://github.com/lowRISC/riscv-llvm#how-can-i-build-upstream-llvmclang-and-use-it-to-cross-compile-for-a-riscv32-target

Leave a Comment