使用 Clang 编译 RISC-V [英] Using Clang to compile for RISC-V

查看:30
本文介绍了使用 Clang 编译 RISC-V的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Clang(版本 12.0.1)为 RISC-V 架构构建一个 hello world 程序.我已经使用 LLVM(版本 12.0.1)安装了它,设置如下:

cmake -G "Unix Makefiles";-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests";-DCMAKE_BUILD_TYPE=调试-DLLVM_ENABLE_ASSERTIONS=开../llvm

根据此处,默认LLVM_TARGETS_TO_BUILDLLVM_ALL_TARGETS,包括 RISC-V.

所以我尝试用 clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world 编译它,我收到错误:

hello_world.c:1:10: 致命错误: 'stdio.h' 文件未找到#include ^~~~~~~~~~产生了 1 个错误.

同时,/opt/risv/,在我安装了riscv-gnu-toolchain的地方,在我的路径中,我可以运行riscv64-unknown-linux-gnu-gcc hello_world.c -o hello_world 没有问题.

我正在尝试使用内核 5.8.0-63-generic 的 Ubuntu 机器.

知道如何解决这个问题并能够通过 Clang 编译 RISC-V 程序吗?

解决方案

预知:

我对此也有同样的错觉:如果 llvm 面向包括 riscv 在内的所有后端,我们应该能够编译我们的代码,只需给出一个像 --target=riscv32 这样的 clang 标志,-target riscv64 等,无需做额外的操作";我有类似的问题,但它不是那样的.虽然LLVM支持riscv target,但是需要指定sysrootgcc 工具链 用于使用 riscv 头文件和库,在另一个你需要的话交叉编译.(因为您当前运行的系统类似于 x86-64,与 riscv 不同,并且您的默认库也不同)这就是您需要链接 riscv-gnu-toolchain 路径的原因.在这里,我假设您从 github 克隆构建了您的 riscv-gnu-toolchain.>

注意: 有些人对第一个选项 (1) 有问题,请先尝试使用其他选项 (2) (3) (4).(查看评论.)

解决方案:

1-) 在构建 llvm 库之前,您可以将这些行添加为 cmake 配置标志:

对于 32 位 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}";

对于 64 位 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}";

然后再次构建llvm库.可能如您所知,在您的 llvm 构建目录中:

cmake --build .

根据您的 cmake 配置进行清除,这是我的示例:

cmake -G "Unix Makefiles";-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests";-DCMAKE_BUILD_TYPE=调试-DLLVM_ENABLE_ASSERTIONS=开-DDEFAULT_SYSROOT=/home/shc/riscv/install/riscv64-unknown-elf"-DGCC_INSTALL_PREFIX=/home/shc/riscv/install";../llvmcmake --build .

您也可以使用另一个 cmake 配置标志将默认目标三元组设置为 riscv:

对于 32 位 riscv:

-DLLVM_DEFAULT_TARGET_TRIPLE=riscv32-unknown-elf"

对于 64 位 riscv:

-DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-elf"

在此之后,您应该能够像这些示例一样编译代码:

对于 C:

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

对于 C++:

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

如果您没有使用 cmake 标志设置默认目标三元组,target 选项应保留:

对于 C:

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

对于 C++:

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

2-) 你可以通过 sysrootgcc 工具链 作为标志(如在上面的 cmake 配置中),同时编译您的代码而无需再次构建您的库.但是,如果要使用它,则需要在每次编译时都给出这些标志:

对于 32 位 riscv:

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

对于 64 位 riscv:

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

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

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-) 您可以尝试在编译时传递这些标志(而不是您的 --target=riscv64 标志),尽管它并不比上述选项更健康.(注意:区别只是linux关键字,一般是-target riscv32-unknown-elf):

对于 32 位 riscv:

-target riscv32-unknown-linux-elf

对于 64 位 riscv:

-target riscv64-unknown-linux-elf

4-) 你可以使用 riscv-llvm repo按照给定的说明进行操作,尽管它已经过时了.

注意:我根据您的示例调整了我的文件位置,以便更好地理解.

您可以在此处查看更多信息:https://github.com/lowRISC/riscv-llvm#how-can-i-build-upstream-llvmclang-and-use-it-to-cross-compile-for-a-riscv32-target

I am trying to build a hello world program using Clang (version 12.0.1) for RISC-V architecture. I have installed it with LLVM (version 12.0.1) with the following setup:

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 
   ../llvm

According to here, default LLVM_TARGETS_TO_BUILD is LLVM_ALL_TARGETS, which includes RISC-V.

So I try to compile it with clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world and I am getting the error:

hello_world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^~~~~~~~~
1 error generated.

At the same time, /opt/risv/, where I have installed the riscv-gnu-toolchain, is in my path, and I can run riscv64-unknown-linux-gnu-gcc hello_world.c -o hello_world without issues.

I am trying on an Ubuntu machine with kernel 5.8.0-63-generic.

Any idea how can I solve this issue and be able to compile RISC-V programs through Clang?

解决方案

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

这篇关于使用 Clang 编译 RISC-V的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆