clang和llvm环境搭建及使用详解

本文详细介绍了如何在Ubuntu 20.04 WSL2环境下,从源码编译LLVM+Clang,并针对远古系统如CentOS7提供了GCC升级及LLVM编译的步骤。内容涵盖了编译参数解析、编译加速技巧以及使用LLVM+Clang工具链的注意事项,包括头文件路径、链接器选择和运行时库的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最直接的方案是从LLVM-project的Github Release页面上下载编译好的二进制包,我的环境是ubuntu-20.04 WSL2,因此可以直接开箱即用。如果是远古系统,例如CentOS7之类的,需要先编译一套GCC-11.2工具链,然后再通过GCC工具链编译LLVM+Clang;

编译llvm+clang

(系统自带GCC版本>5的情况)

cmake -H. -Bbuild_release -DCMAKE_BUILD_TYPE=Release \
-G "Ninja" \
-DLLVM_USE_LINKER="gold" \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb" \
-DLLVM_ENABLE_RUNTIMES="libc;compiler-rt;libcxx;libcxxabi;libunwind"

参数解释

  • -H.:表示从当前目录.获取CMakeLists.txt
  • -Bbuild:表示将构建文件输出到当前目录下的./build_release目录,如无则新建目录;
  • -DCMAKE_BUILD_TYPE=Release:采用Release方式编译,好处在于编译产物体积较小;
  • -G "Ninja":采用ninja作为构建工具,好处是能够利用多核多CPU加快编译速度,坏处是内存消耗较大;
  • -DLLVM_USE_LINKER="gold":采用gnu-gold作为连接器,好处是比普通的gnu-ld速度快,内存开销小;
  • -DLLVM_TARGETS_TO_BUILD="X86":只编译目标平台X86,可以减少编译所需的时间(根据实际目标平台决定);
  • -DLLVM_ENABLE_PROJECTS:编译项目列表
    • clang:编译器前端,以及一些相关的编译器前端工具集;
    • clang-tools-extra:额外的clang工具,如:clangdclang-format等;
    • lld:LLVM的链接器,链接速度贼快,LLVM+CLANG工具集必选;
    • lldb:LLVM项目的调试器,作用和GDB一样;
  • -DLLVM_ENABLE_RUNTIMES:编译的运行时列表:
    • libc:LLVM后端的libc运行时库;
    • compiler-rt:LLVM后端的编译器运行时库;
    • libcxx:作为libstdc++的替代,LLVM后端的C++运行时库;
    • libcxxabi:LLVM后端的C++二级制接口运行时库;
    • libunwind:LLVM后端的栈回滚库,主要是用于获取程序的调用栈和异常处理和跳转需要;

如果是远古操作系统,编译的命令参考如下(GCC-11.2编译可以参考我之前的文章Ubuntu20.04 LTS 安装GCC11.2教程,包教包会!):

# 注意 TOOL变量代表了GCC-11.2安装的目录 根据实际情况自行设置环境变量
export CC=$TOOL/bin/gcc 
export CXX=$TOOL/bin/g++ 
cmake -H. -Bbuild_release -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$TOOL/lib64 -L$TOOL/lib64 -L/usr/local/lib" \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb" \
-DLLVM_ENABLE_RUNTIMES="libc;compiler-rt;libcxx;libcxxabi;libunwind" \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=1 \
-G "Ninja"

最重要的的两个参数,是传递给CMake的:

  • -DCMAKE_CXX_LINK_FLAGS:在编译clang+llvm时使用给定的rpath作为链接路径,如果不使用,默认链接的是远古CentOS自带的4.8.5版本GNU工具链,它是不满足llvm项目的编译要求的;
  • -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=1:允许在安装时导入编译期链接阶段的rpath路径,不需要在安装后手动指定$LD_LIBRARY_PATH路径,安装好的clang+llvm运行时自动会查找编译时的rpath路径,也就是上面传递的-Wl,-rpath,$TOOL/lib64的位置(即GCC-11.2运行时的安装位置,可以通过readelf -d executable |grep RPATH验证,这里就不多说明了)

使用clang+llvm工具链的详细说明

直接安装二进制包的情况下,使用clang filename编译文件会发生链接错误,因为找不到对应的头文件;需要使用-lstdc++指定本机的gnu工具集后端,才能正常编译;如果要完全采用LLVM+Clang工具链编译,需要使用:

clang filename.cc --stdlib=libc++ -fuse-ld=lld -lc++

我们可以比较一下两种方式的-v输出内容(左为clang+gnu,右为clang+llvm):
在这里插入图片描述

  1. 使用-lstdc++编译的时候,注意序号1处的差异;可以看出,此时编译的后端采用的还是GNU工具集,尤其重点是:

    • 左边引入的C++头文件来自/usr/lib/gcc/X86_64-linux-gnu/10/../../../../include/c++/10下面;这个位置实际上就是/usr/include/c++/10,也就是系统自带的GNU工具链的C++头文件所在地;
    • 右边引入的C++头文件来自/usr/local/llvm-13.0.1/bin/../include/c++/v1;这个地方正是我们安装LLVM+Clang工具链所在的位置;
  2. 在第2处差异,可以明显看出include <...> search查找头文件的路径发生了区别,在1中已经描述过了;

  3. 在第3处差异,可以明显看到链接器的区别,左为/usr/bin/ld,右为/usr/local/bin/ld.lld(注意,这里我在/usr/local/bin下建立了ld.lld的软连接,默认是没有的);同时,链接过程载入的运行时库也是完全不同的,左边载入的是GNU的libstdc++,右边载入的是LLVM的libc++

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值