这是永恒软件计划的根仓库。
ESI 定义了一种极简的机器架构(基于对 Subleq OISC 的修改),其简单程度使得完整规范可以写在餐巾纸上。我们随后为该架构提供了 LLVM 编译器后端、Linux 的移植、C/C++ 运行时库的移植,以及其他工具(包括一个约 50 行 C 代码的参考虚拟机实现),用于从现有软件构建并运行一个自包含的“胶囊”。
这一切的意义何在?运行当今的软件需要在专有且文档不完整的硬件之上,依赖一套复杂的依赖栈(编译器、库、框架、操作系统),这使得确保当今的软件在未来仍能继续运行变得非常困难。这种“比特腐烂”问题对于任何在数年或数十年时间跨度内维护遗留软件的人来说都耳熟能详,但现在想象一下 1000 年后的历史学家试图理解 21 世纪的生活,而其中大部分体验都是通过软件获得的。即使今天的软件二进制文件被保存下来,也很难想象这些二进制文件仍然可以运行。像 QEMU 这样的模拟器只是把这个问题挪了个地方,并没有解决它:它们同样有着类似复杂的软件和硬件依赖栈,因此也无法在遥远的未来运行。
ESI 通过以下方式解决这个问题:(1) 定义一种简单到可以写在餐巾纸上,但又强大到足以高效表示任何软件的架构,并且不需要了解任何专有硬件、软件、框架等;(2) 实现一套工具链,将任何现有软件编译成该架构的自包含“胶囊”。这确保了只要胶囊二进制文件和餐巾纸说明得以保存,软件就可以在遥远的未来被复活和体验,而无需假设对当今计算系统有任何了解。
本仓库包含构建和运行你自己的 ESI 机器,以及从现有软件构建 ESI“胶囊”所需的一切。
有关 ESI 使命的更多信息,请参见:https://www.eternal-software.org
本仓库以子模块形式包含 LLVM 工具链、Linux 内核、uClibc-ng 和 Busybox 的 ESI 分支。这些都必须一起检出。
git clone --recurse-submodules https://github.com/adriancable/eternal
你需要 SDL3 来构建 ESI 虚拟机。使用例如 apt install libsdl3-dev 安装。没有其他依赖。SDL3 可以很容易地被任何其他用于写入像素和捕获键盘事件的方式替代,无论是现在还是将来。
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
当 Linux 启动后,可以尝试例如:
cd doom
./doom
ESI 工具链应该可以在任何 Linux 系统上以极少的努力构建。我们也已在 macOS 上成功构建,但需要一些修改。确保你已安装并可使用 gcc、python3、CMake、ninja、flex、bison。
从检出的 eternal 文件夹开始。
rm -rf llvm-project/build && mkdir -p llvm-project/build
cmake -G Ninja -S llvm-project/llvm -B llvm-project/build -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_BUILD_TOOLS=ON -DLLVM_ENABLE_ASSERTIONS=OFF -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="Subleq" -DLLVM_DEFAULT_TARGET_TRIPLE="subleq-unknown-linux" -DLLVM_FORCE_VC_REPOSITORY="ESI" -DLLVM_FORCE_VC_REVISION=""
cd llvm-project/build
ninja llc clang llvm-mc lld llvm-objcopy llvm-ar llvm-ranlib llvm-nm llvm-readelf llvm-strip llvm-objdump
cd ../../linux
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy \
INSTALL_HDR_PATH=../runtime/sysroot/kernel-headers \
headers_install
cd ../uclibc-ng
make ARCH=subleq defconfig
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
PREFIX=../runtime/sysroot \
STRIPTOOL=../llvm-project/build/bin/llvm-strip \
DEVEL_PREFIX=/ \
install_dev
cd ../runtime
./build_and_install_runtime.sh
./build_libcxx.sh
ninja -C ./libcxx install
cd ../busybox
make subleq_defconfig
make CC=../llvm-project/build/bin/clang \
AR=../llvm-project/build/bin/llvm-ar \
STRIP=../llvm-project/build/bin/llvm-strip
mkdir ../initramfs_root/bin
cp busybox ../initramfs_root/bin/busybox
cd ../linux
export KBUILD_BUILD_USER="root"
export KBUILD_BUILD_HOST="eternal"
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy \
defconfig
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy
cd ..
python3 tools/make_boot_image.py --stack-size 536870912 linux/vmlinux
./vm/vm linux/vmlinux.bootimage
完成后输入 exit 以终止虚拟机。
标准的交叉编译工作流程。为了快速上手,我们提供了一个便捷脚本(clang_userspace.sh),它会设置环境并调用 clang。
cat << 'EOF' > hello.c
#include <stdio.h>
int main() {
printf("Hello, ESI world!\n");
return 0;
}
EOF
tools/clang_userspace.sh hello.c
cp hello.elf initramfs_root/root
然后重新构建 initramfs 和胶囊:
cd linux
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy
cd ..
python3 tools/make_boot_image.py --stack-size 536870912 linux/vmlinux
启动虚拟机:
./vm/vm linux/vmlinux.bootimage
一旦 Linux 启动:
./hello.elf
为当今的开发者提供,以理解该架构和工具链。对于 1000 年后想要复活胶囊并运行其中软件的人来说,这些内容(除了餐巾纸)都不是必需的。
make 是图灵完备的,因此可以运行 Subleq 虚拟机如果你已将 ESI 虚拟机移植到新平台,请通过提交 Issue 告知我们,我们会将其添加到此列表中。
ESI 虚拟机的压缩版本(366 字节的 C 代码)是第 29 届 IOCCC 竞赛的获胜者。