使用 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=Debug \
   -DLLVM_ENABLE_ASSERTIONS=On \
   ../llvm

根据here,默认LLVM_TARGETS_TO_BUILDLLVM_ALL_TARGETS,其中包括RISC-V。

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

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

同时,我安装了 /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 程序吗?

cecilia53520 回答:使用 Clang 编译 RISC-V

预知:

我对此也有同样的错觉:“如果 llvm 面向包括 riscv 在内的所有后端,我们应该能够编译我们的代码,只需给出一个像 --target=riscv32-target riscv64 之类的 clang 标志,而无需执行额外的操作”,我有 similar question,但事实并非如此。虽然 LLVM 支持 riscv 目标,但您需要指定 sysrootgcc toolchain 以使用 riscv 头文件和库,换句话说,您需要 cross compilation。 (因为您当前运行的是与 riscv 不同的 x86-64 系统,并且您的默认库不同)这就是您需要链接 riscv-gnu-toolchain 路径的原因。在这里,我假设您从 github 克隆构建了您的 riscv-gnu-toolchain

解决方案:

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=Debug \
   -DLLVM_ENABLE_ASSERTIONS=On \
   -DDEFAULT_SYSROOT="/home/shc/riscv/install/riscv64-unknown-elf" \
   -DGCC_INSTALL_PREFIX="/home/shc/riscv/install" \
   ../llvm

cmake --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 toolchain 作为标志(如上面的 cmake 配置)传递,而无需再次构建库。但是,如果要使用它,则需要在每次编译时都给出这些标志:

对于 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

本文链接:https://www.f2er.com/14335.html

大家都在问