在 Arch Linux 上编译 bloomberg/clang-p2996 小记
本文简要记录笔者在 Arch Linux 上编译一个部分支持 C++ 反射的 clang 编译器的过程。
期待 Reflection 能正式被编译器实现的那一天。 :)
本次实验受群友 Yiran Wang 启发。
克隆仓库
GitHub 仓库在 这里,有关这个编译器的介绍详情请看仓库(默认是 purpose 分支,代码在 p2996 分支上)。
先克隆仓库到本地:
使用 --depth 1
选项只克隆最新版本的 commit,可大大减小仓库体积(好像只有两百多兆)。
有的仓库有很多分支(比如 llvm 或者 gcc 官方仓库),使用 --branch=xxx
指定克隆某一个分支也可以减小体积。本仓库只有两个分支,作用不大。
建议上网搜一下镜像站,在高级搜索中调整搜索范围为近一周左右,基本就可以找到可用的镜像站,实测有助于提高网速。
编译 Clang
编译选项和步骤可以参考 llvm 官网手册中的介绍,此处给出我的生成命令,供参考:
$ cd clang-p2996
$ mkdir build
$ cd build
$ cmake -DLLVM_ENABLE_PROJECTS=clang \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_ENABLE_RUNTIMES="libc;libcxx;libcxxabi;libunwind" \
-DCMAKE_C_FLAGS="-O3 -march=native -mtune=native" \
-DCMAKE_CXX_FLAGS="-O3 -march=native -mtune=native" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_USE_LINKER=lld \
-DLLVM_BUILD_TOOLS=OFF \
-DLLVM_BUILD_EXAMPLES=OFF \
-DLLVM_BUILD_TESTS=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_DOCS=OFF \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DCMAKE_INSTALL_PREFIX=/usr/local/llvm-build \
-G "Unix Makefiles" \
../llvm
具体每一个选项是什么意思以及有哪些可选参数,自己 STFW 或者问 AI。此处仅为精简编译(仅编译 clang),没有添加其他的各种工具。有需者请自选。
值得注意的是,-DLLVM_ENABLE_RUNTIMES
应该至少有 libc;libcxx;libcxxabi;libunwind
(感谢群友 Yiran Wang)。
强行添加了 -O3 -march=native -mtune=native
,纯属个人喜好。
-DCMAKE_INSTALL_PREFIX=/usr/local/llvm-build
的结果是 llvm-build
下有 bin
、lib
等等这些。以免有人怀疑是否会出现重叠安装目录的情况。
如果有提示缺少依赖就安装相应的依赖(貌似是不缺)。
编译的时候,需要注意一下编译使用的任务数,因为可能会遇到内存瓶颈。我在 14 核心 20 线程的笔记本 U 上使用 make -j20
编译会在进度到 55% 左右时直接吃满 32G 内存 + 9G 交换内存导致桌面卡死。解决方法之一是改为 make -j14
。
测试运行
先贴一个简单的编译命令:
$ /usr/local/llvm-build/bin/clang++ main.cpp \
--std=c++26 \
-I/usr/local/llvm-build/include/c++/v1 \
-I/usr/local/llvm-build/include/x86_64-unknown-linux-gnu/c++/v1 \
-freflection \
-stdlib=libc++ \
-Wl,-rpath,/usr/local/llvm-build/lib/x86_64-unknown-linux-gnu \
-g3 -Og -march=native -mtune=native
别忘了使用 -freflection
。
-stdlib=libc++
必不可少,否则一顿 -I
也会报错。
仅仅 -L/usr/local/llvm-build/lib/x86_64-unknown-linux-gnu
貌似不行。
贴一段简单的测试程序:
#include <experimental/meta>
#include <print>
int main()
{
constexpr auto r = ^int;
typename[:r:] x = 42; // Same as: int x = 42;
typename[:^char:] c = '*'; // Same as: char c = '*';
std::println("{}", std::same_as<decltype(x), int>);
std::println("{}", std::same_as<decltype(c), char>);
}
输出结果为: