llvm是一个编译器框架,据说比gcc好。本文带领大家编译一次linux内核。注意要llvm9才能默认支持编译内核。
整体构建的过程有三种:
整体编译简单,独立编译易于独立控制,各有好处。
LLVM项目包含有很多小的子项目,他们之间的作用和依赖关系:
编译器和库没有必然的绑定关系,c 语言标准库一般使用系统自带的GNU GCC libc,LLVM也提供了一个,但是隐藏的很深。而c++库就复杂得多,标准库有多个实现,GNU的libstdc++,然后可以选择依赖的二进制接口,GNU的libsupc++等。
llvm官网只提供了linux版的源代码,而没有提供编译好的包,因此首先要自己编译一下最新的llvm代码。deepin系统自带最新版本是llvm-6.0版,就用这个来编译。
第一步 前期准备
sudo apt install llvm-6.0 #llvm框架
sudo apt install clang-6.0 #c/c++编译前端
sudo apt install lld-6.0 #链接器
#deepin的相关安装并没有产生默认的工具名字,因此要自己弄一个软链接
sudo ln -sr /usr/bin/clang-6.0 /usr/bin/clang #默认的c编译器
sudo ln -sr /usr/bin/clang++-6.0 /usr/bin/clang++ #默认的c++编译器
sudo ln -sr /usr/bin/lld-6.0 /usr/bin/lld #默认的lld编译器
#安装构建工具
sudo apt install cmake ninja-build
第二步 下载源代码
可以通过下载.sig文件来检验数据pgp签名:345AD05D ,公钥文件:http://releases.llvm.org/9.0.0/hans-gpg-key.asc
wget http://releases.llvm.org/9.0.0/hans-gpg-key.asc
pgp --import hans-gpg-key.asc #导入公钥
wget http://releases.llvm.org/9.0.0/llvm-9.0.0.src.tar.xz http://releases.llvm.org/9.0.0/llvm-9.0.0.src.tar.xz.sig
pgp --verify http://releases.llvm.org/9.0.0/llvm-9.0.0.src.tar.xz.sig #用sig文件验证签名
或者可以去清华大学开源镜像站下载: https://mirrors.tuna.tsinghua.edu.cn/help/llvm/
第三步 编译安装
将源代码压缩包解压后,注意不要在源代码文件夹内继续操作,而应该新建一个新的目录来构建。
目录:
llvm目录结构:
cmake 一个生成其他构建工具项目的通用构建工具:
-G Ninja
cmake默认导出是make项目,速度极度慢,要好几个小时,导出Ninja项目可以缩短时间-DCMAKE_BUILD_TYPE=Release
构建发行版,大小约1G,默认debug版,大小达到惊人的20G!-DLLVM_ENABLE_LLD=ON
使用lld链接器-DCMAKE_C_COMPILER=clang
使用clang 做c编译器-DCMAKE_CXX_COMPILER
使用clang++ 做c++编译器-DLLVM_TARGETS_TO_BUILD="ARM;X86;AMDGPU;RISCV;WebAssembly"
指定后端编译架构../llvm-9.0.0.src/
源代码的目录-DCMAKE_INSTALL_PREFIX
最终文件安装的目录-DLLVM_BUILD_LLVM_DYLIB=on
动态链接库-DLLVM_LINK_LLVM_DYLIB=on
-DLLVM_ENABLE_RUNTIMS
使用当前构建的工具-DLLVM_DISTRIBUTION_COMPONENTS
同时构建的组件-DLLVM_TUNTIME_DISTRIBUTION_COMPONENTS
运行时组件-DLLVM_DYLIB_COMPONENTS
动态库的组件-DLLVM_INSTALL_TOOLCHAIN_ONLY
不安装开发LLVM本身的相关工具cd llvm
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_LLD=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_INSTALL_PREFIX=~/.local -DLLVM_BUILD_LLVM_DYLIB=on -DLLVM_LINK_LLVM_DYLIB=on ../llvm-9.0.0.src/
#ninja 一个快速构建项目的工具
#用ninja构建,大概要半个小时以上
# -j 4 开启 4 线程编译
ninja -j 4
sudo ninja install #安装构建完的工具
程序依赖公共的库文件,因此要厘清他们之间的关系,这样才不会陷入依赖陷阱。
名称 | 典型文件 | 项目组 | 说明 |
---|---|---|---|
compiler-rt | libclang_rt.builtins.<arch>.a |
LLVM | 编译器运行时,支持非原生的硬件操作、原子库 |
libunwind | libunwind.a | LLVM | unwind 栈异常展开 |
libgcc_s | libgcc_s.so.1 | GNU | 编译器运行时、Unwind ABI |
libatomic | GNU | 原子库 | |
sanitizer | libclang_rt.<sainitizer>.<arch>.a |
LLVM | 边界检测 |
libc++ abi | libc++abi.a | LLVM | c++ ABI |
libsupc++ | GNU | c++ ABI | |
libc++ | libc++.so | LLVM | c++标准库 |
libstdc++ | libstdc++.so.6 | GNU | c++标准库 |
libc | libc.so.6 | GNU | c标准库 |
LLVM依赖关系如下:
GNU依赖如下:
cd clang
# -DLLVM_PATH=../llvm-9.0.0.src/ 指定LLVM目录
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_LLD=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_PATH=../llvm-9.0.0.src/ ../cfe-9.0.0.src/
ninja
sudo ninja install
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_LLD=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_PATH=../llvm-9.0.0.src/ ../lld-9.0.0.src/
ninja
sudo ninja install
可选参数:
# 这个要求
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS="-Wl,--rpath=/opt/glibc/lib -Wl,--dynamic-linker=/opt/glibc/lib/ld-linux-x86-64.so.2" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_LINKER=$(which ld.lld) -DLLVM_ENABLE_LLD=ON ../lldb-9.0.0.src/
ninja
sudo ninja install
可选参数:
# 编译这个感觉比较奇怪,要求在上级目录有名为libcxx和libcxxabi的源文件
ln -sr libcxxabi-9.0.0.src/ libcxxabi
ln -sr libcxx-9.0.0.src/ libcxx
cd complier-rt
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_LINKER=$(which ld.lld) -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ../compiler-rt-9.0.0.src/
ninja
sudo ninja install
rm libcxxabi libcxx
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_LINKER=lld -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ../libunwind-9.0.0.src/
ninja
sudo ninja install
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_LINKER=lld -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLIBCXXABI_LIBCXX_INCLUDES=../libcxx-9.0.0.src/include/ ../libcxxabi-9.0.0.src/
ninja
sudo ninja install
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_LINKER=lld -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ../libcxx-9.0.0.src/
ninja
sudo ninja install
将所有子项目下载下来,放在llvm 同级目录中。
比如:
clang、compiler-rt、libcxxabi、lldb、clang-tools-extra 、libcxx、lld、llvm、libunwind、libc
选项说明:
-DLIBCXX_USE_COMPILER_RT=YES
libcxx使用compiler-rt而不是libgcc_s-DLIBCXXABI_USE_COMPILER_RT=YES
libcxxabi 同上-DLLVM_ENABLE_PROJECTS="libunwind;clang;compiler-rt;debuginfo-tests;libclc;llgo;mlir;parallel-libs;pstl;openmp;polly;libcxxabi;clang-tools-extra;libcxx;lld;lldb;libc"
同时编译子项目-DLLVM_ENABLE_LIBCXX=on
使用libc++而不是libstdc++-DLIBCXX_CXX_ABI=libcxxabi
使用libcxxabi,而不是其他 libsupc++ 等-DLIBCXXABI_USE_LLVM_UNWINDER=on
使用libunwind-DLLVM_ENABLE_RUNTIMS
使用当前构建的工具-G Ninja
cmake导出Ninja项目可以缩短时间-DCMAKE_BUILD_TYPE=Release
构建可发行版-DLLVM_ENABLE_LLD=ON
使用lld链接器-DCMAKE_C_COMPILER=clang
使用clang 做c编译器-DCMAKE_CXX_COMPILER=clang++
使用clang++ 做c++编译器-DLLVM_TARGETS_TO_BUILD="host"
指定后端编译架构-DCMAKE_INSTALL_PREFIX=~/.local
最终文件安装的目录-DLLVM_INSTALL_TOOLCHAIN_ONLY=on
不安装开发LLVM本身的相关工具-DCLANG_ENABLE_BOOTSTRAP=on
二次编译(生成当前版本,然后用当前版本再次编译)-DLLVM_PARALLEL_COMPILE_JOBS=4
: 并行编译线程数-DLLVM_PARALLEL_LINK_JOBS=4
: 并行链接线程数cmake -G Ninja -DLLVM_PARALLEL_COMPILE_JOBS=4 -DLLVM_PARALLEL_LINK_JOBS=4 -DLLVM_TARGETS_TO_BUILD="host" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_LLD=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_ENABLE_LIBCXX=on -DLIBCXX_CXX_ABI=libcxxabi -DLLVM_INSTALL_TOOLCHAIN_ONLY=on -DLLVM_ENABLE_PROJECTS="libunwind;clang;compiler-rt;debuginfo-tests;libclc;llgo;mlir;parallel-libs;pstl;openmp;polly;libcxxabi;clang-tools-extra;libcxx;lld;lldb;libc" -DCMAKE_INSTALL_PREFIX=~/.local ../llvm-project/llvm
cmake --build .
动态链接库由ldconfig 配置,默认跟踪:
可以通过以下配置增加目录:
sudo ldconfig
更新动态链接库缓存
环境变量搜索路径:
构建
同样方法,可以构建其他工具:clang,complier-rt;
lld需要使用-DLLVM_ENABLE_LLD=OFF,lldb需要先安装swig4、libeidt-dev、libncurses5-dev、build-essential、正确的python版本(我在最后链接阶段失败了)。
# apt源秘钥
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
apt source:
deb http://apt.llvm.org/buster llvm-toolchain-stretch main
deb-src http://apt.llvm.org/buster llvm-toolchain-stretch main
cc命令是个链接,链接到gcc,改成clang。c++命令同样如此,改成clang++。然后编译内核即可。
sudo make CC=clang xconfig #CC指定编译器设置编译配置
make deb-pkg CC=clang -j4
事实上,以上方法只是修改了环境参数CC指向clang,即llvm的c编译器,编译系统可以识别这个参数。另外还可以精细的设置相关环境变量:
如果是debian的.config配置,最好是把安全启动给关闭,因为后续安装其他模块和工具会比较麻烦。