第 22.12 节 code-server 和 clangd
警告
本教程目前在 13.2-RELEASE 和 14.0-RELEASE 上测试正常,其他版本请慎重参考。
服务器启用 Linux 二进制兼容,并部署 archlinux-bootstrap 镜像
# service linux enable
# service linux start
# fetch -o /tmp https://mirrors.bfsu.edu.cn/archlinux/iso/latest/archlinux-bootstrap-x86_64.tar.zst
# tar --use-compress-program=unzstd -xpvf archlinux-bootstrap-x86_64.tar.zst -C /tmp --numeric-owner
# rm archlinux-bootstrap-x86_64.tar.zst
# cp -Rf /tmp/root.x86_64/* /compat/linux
服务器配置 pacman 源,并添加 archlinuxcn 仓库
编辑 /compat/linux/etc/pacman.conf
,写入:
[options]
Architecture = auto
ParallelDownloads = 5
[core]
Server = https://mirrors.cernet.edu.cn/archlinux/\$repo/os/\$arch
SigLevel = Required DatabaseOptional
[extra]
Server = https://mirrors.cernet.edu.cn/archlinux/\$repo/os/\$arch
SigLevel = Required DatabaseOptional
[archlinuxcn]
Server = https://mirrors.cernet.edu.cn/archlinuxcn/\$arch
SigLevel = Required DatabaseOptional
服务器初始化 Arch Linux 运行时环境
# chroot /compat/linux pacman-key --init
# chroot /compat/linux pacman-key --populate
服务器更新 Arch Linux 运行时环境,并安装 code-server
编辑 /etc/resolv.conf /compat/linux/etc
,写入:
# chroot /compat/linux pacman -Syu --noconfirm
# chroot /compat/linux pacman -S --noconfirm archlinuxcn-keyring
# chroot /compat/linux pacman -S --noconfirm code-server
服务器删除 Arch Linux 运行时环境中的无用目录
# rm -Rf /compat/linux/home
# rm -Rf /compat/linux/root
# rm -Rf /compat/linux/usr/local
# rm -Rf /compat/linux/usr/src
服务器安装 llvm 与 clangd 插件
# pkg install -y llvm
# ln -sf /compat/linux/lib/code-server/bin/code-server /usr/local/bin
# code-server --install-extension llvm-vs-code-extensions.vscode-clangd
服务器通过 daemon 命令启动 code-server
# daemon -p /root/.code-server.pid -f code-server --auth=none
客户端通过 SSH 建立隧道并通过浏览器连接到 code-server 服务器
# ssh -L 8080:127.0.0.1:8080 -N root@server
在浏览器中访问 http://127.0.0.1:8080
(示例)浏览器中用 code-server 打开 FreeBSD 的源码树
# code-server /usr/src
(示例)浏览器中编译最小化内核并生成 compile_commands.json
文件
compile_commands.json
文件# pkg install bear
# bear --append -- make KERNCONF=MINIMAL buildkernel
等待编译完成并生成 compile_commands.json
文件,然后你就可以开始阅读内核关键部分的源码了。
自动化安装脚本
为了便于读者快速获得开发环境,我们将安装 code-server 的步骤整理成一个脚本:
#!/bin/sh
set -e
ARCHLINUX_MIRROR="https://mirrors.cernet.edu.cn/archlinux"
ARCHLINUXCN_MIRROR="https://mirrors.cernet.edu.cn/archlinuxcn"
FREEBSD_PKG_MIRROR="https://mirrors.cernet.edu.cn/FreeBSD-pkg"
umount -Af
rm -Rf /compat/linux
rm -Rf /tmp/archlinux-bootstrap-x86_64.tar.zst
rm -Rf /tmp/root.x86_64
service linux enable
service linux start
fetch -o /tmp "$ARCHLINUX_MIRROR/iso/latest/archlinux-bootstrap-x86_64.tar.zst"
tar --use-compress-program=unzstd -xpvf archlinux-bootstrap-x86_64.tar.zst -C /tmp --numeric-owner
cp -Rf /tmp/root.x86_64/* /compat/linux
cat >/compat/linux/etc/pacman.conf <<EOF
[options]
Architecture = auto
ParallelDownloads = 5
[core]
Server = $ARCHLINUX_MIRROR/\$repo/os/\$arch
SigLevel = Required DatabaseOptional
[extra]
Server = $ARCHLINUX_MIRROR/\$repo/os/\$arch
SigLevel = Required DatabaseOptional
[archlinuxcn]
Server = $ARCHLINUXCN_MIRROR/\$arch
SigLevel = Required DatabaseOptional
EOF
chroot /compat/linux pacman-key --init
chroot /compat/linux pacman-key --populate
cp /etc/resolv.conf /compat/linux/etc
chroot /compat/linux pacman --sync --refresh --sysupgrade --noconfirm
chroot /compat/linux pacman --sync --needed --noconfirm archlinuxcn-keyring
chroot /compat/linux pacman --sync --needed --noconfirm code-server
ln -sf /compat/linux/lib/code-server/bin/code-server /usr/local/bin
rm -Rf /compat/linux/home
rm -Rf /compat/linux/root
rm -Rf /compat/linux/usr/local
rm -Rf /compat/linux/usr/src
pkg upgrade -y git bash vim htop tmux llvm bear
code-server --install-extension llvm-vs-code-extensions.vscode-clangd
code-server --install-extension mhutchie.git-graph
rm -Rf /tmp/archlinux-bootstrap-x86_64.tar.zst
rm -Rf /tmp/root.x86_64
欢迎测试与反馈。
FAQ 常见问题
为什么要有这篇教程?
通过在 FreeBSD 上安装并配置 code-server,你无需安装桌面环境即可在原生 FreeBSD 环境中获得集成开发环境。这使你能够利用熟悉的 VSCode 界面和强大的 clangd 插件来支持 FreeBSD 内核的开发,从而大大降低了投入 FreeBSD 代码贡献以及二次开发所需的学习成本。
为什么要用 Arch Linux 兼容层?
由于上游的 FreeBSD 版 code-server 存在问题,历史版本中仅有一个修订版可用。因此通过 Linux 兼容层运行 code-server 是目前最省时省力的方案。此外,自 code-server 基于 Node.js 18 以来,对 glibc 的最低版本要求提高,CentOS 提供的运行时环境已无法满足其需求。
兼容层?那还能用来搞 FreeBSD 的开发吗?
当然可以,虽然为了运行 code-server 我们使用了 Linux 兼容层,但 clangd 以及其他所有开发工具仍然完全由 FreeBSD 提供。
为什么 clangd 还有任何其他开发工具将全部由 FreeBSD 提供?
如你所见,综合考虑各种因素后,code-server 目前运行在 FreeBSD 的 Linux 二进制兼容模式下。但首先我们要明确,这只是 Linux 二进制兼容模式,不是 Linux 模拟器模式,更不是 Linux 虚拟机模式。既然是二进制兼容,那么运行 Linux 程序的主体仍然是 FreeBSD 内核本身,并没有额外多出一个 Linux 内核。
由于主体仍是 FreeBSD 内核,这必然涉及到 Linux 程序和 FreeBSD 程序的混合运行,而混合运行又会带来动态链接库调用的问题。对于一个已经编译好的二进制程序来说,它所需的动态链接库路径是写死的,比如如果某个 Linux 二进制程序依赖 /lib/glibc.so
,那么它一定会去 /lib/glibc.so
查找这个文件,而非其他地方。但在 FreeBSD 上,Linux 的运行时环境位于 /compat/linux
目录下。
为了解决这个问题,有两种方法。一种是给 Linux 二进制程序打补丁,将其依赖的 /lib/glibc.so
修改为 /compat/linux/lib/glibc.so
,但这种做法不仅复杂,而且难免会有遗漏。另一种方法是 FreeBSD 在内核层面劫持路径,当一个 Linux 二进制程序尝试 open
/lib/glibc.so
时,FreeBSD 内核会自动在路径前加上 /compat/linux
,使其变为 /compat/linux/lib/glibc.so
。这一过程对应用程序而言是透明的,应用程序自身并不知道它最终获得的是哪个文件,但从 FreeBSD 内核的视角来看,它实际访问的是 /compat/linux/lib/glibc.so
。
如果某个文件不在 /compat/linux
目录下,而是在 FreeBSD 本地系统目录中,FreeBSD 内核会自动 fallback 到原始路径进行二次尝试。如果这次仍然找不到文件,open
系统调用才会真正失败。
回到 code-server,它作为一款 Linux 程序,在尝试访问文件或目录时,默认会先在 /compat/linux
下查找。假设你想打开 /usr/src
目录来查看 FreeBSD 的源码树,如果 /compat/linux/usr/src
存在,那么被打开的实际上是 /compat/linux/usr/src
,而不是你真正想要的 /usr/src
。这时,我们需要删除 /compat/linux/usr/src
,确保 FreeBSD 内核能够 fallback 到正确的 /usr/src
。
同样的逻辑也适用于 clangd。由于 /compat/linux/bin/clangd
并不存在,当 code-server 试图启动 clangd 时,它最终会调用 FreeBSD 提供的 /usr/local/bin/clangd
,其他开发工具也同理。这就是为什么即使 code-server 运行在 Linux 兼容层上,clangd 以及其他所有开发工具仍然完全由 FreeBSD 提供。
还有什么需要补充的内容?
如何在服务器上通过 HTTPS 来提供 code-server 服务
探讨 Linux 兼容层与 Linux Jail 究竟有何区别
你这是在鼓励用户当 root 敢死队?
永言配命,自求多福。
风险自负。
最后更新于