
Minimale Maschinenarchitektur mit LLVM-Compiler-Backend, Linux-Port und virtueller Maschine zur Erstellung in sich geschlossener Software-Kapseln, die unbegrenzt lauffähig bleiben ohne komplexe Abhängigkeiten.
Dies ist das Haupt-Repository für die Eternal Software Initiative.
Die ESI definiert eine minimale Maschinenarchitektur (basierend auf einer Modifikation der Subleq-OISC), die so einfach ist, dass ihre vollständige Spezifikation auf eine Serviette geschrieben werden kann. Wir stellen dann ein LLVM-Compiler-Backend für diese Architektur bereit, einen Linux-Port, Ports der C/C++-Laufzeitbibliotheken und andere Werkzeuge (einschließlich einer Referenzimplementierung einer virtuellen Maschine in ~50 Zeilen C), die erforderlich sind, um eine eigenständige 'Kapsel' aus vorhandener Software zu bauen und auszuführen.
Was ist der Sinn all dessen? Um heutige Software auszuführen, ist ein komplexer Stapel von Abhängigkeiten (Compiler, Bibliotheken, Frameworks, Betriebssystem) auf proprietärer und unvollständig dokumentierter Hardware erforderlich, was es sehr schwierig macht, sicherzustellen, dass heutige Software auch in Zukunft noch funktioniert. Dieses Problem des 'Bit-Rot' ist jedem bekannt, der Legacy-Software über Jahre oder Jahrzehnte hinweg wartet, aber stellen Sie sich einen Historiker in 1.000 Jahren vor, der versucht, das Leben im 21. Jahrhundert zu verstehen, das zu einem großen Teil durch Software erlebt wird. Selbst wenn heutige Software-Binärdateien erhalten bleiben, ist es weit hergeholt, sich vorzustellen, dass diese Binärdateien immer noch ausführbar sind. Emulatoren wie QEMU verschieben dieses Problem nur, lösen es aber nicht: Auch sie haben einen ähnlich komplexen Stapel von Software- und Hardwareabhängigkeiten und werden daher in ferner Zukunft ebenfalls nicht ausführbar sein.
Die ESI löst dieses Problem, indem sie (1) eine Architektur definiert, die einfach genug ist, um auf eine Serviette geschrieben zu werden, aber leistungsstark genug, um jede Software effizient darzustellen, ohne Kenntnisse über proprietäre Hardware, Software, Frameworks usw. zu erfordern, und (2) eine Toolchain implementiert, um jede vorhandene Software in eine eigenständige 'Kapsel' für diese Architektur zu kompilieren. Dies stellt sicher, dass die Software – vorausgesetzt, die Kapsel-Binärdatei und die Serviettenanweisungen bleiben erhalten – in ferner Zukunft wiederbelebt und erlebt werden kann, ohne dass Kenntnisse über heutige Computersysteme vorausgesetzt werden.
Dieses Repository enthält alles, was benötigt wird, um Ihre eigene ESI-Maschine zu bauen und auszuführen und ESI-'Kapseln' aus vorhandener Software zu bauen.
Weitere Informationen zur Mission der ESI finden Sie unter: https://www.eternal-software.org
Dieses Repository enthält als Submodule ESI-Forks der LLVM-Toolchain, des Linux-Kernels, von uClibc-ng und Busybox. Diese müssen alle zusammen ausgecheckt werden.
git clone --recurse-submodules https://github.com/adriancable/eternal
Sie benötigen SDL3, um die ESI-VM zu bauen. Installieren Sie es z. B. mit apt install libsdl3-dev. Es gibt keine anderen Abhängigkeiten. SDL3 kann leicht durch jede andere Methode zum Schreiben von Pixeln und Erfassen von Tastaturereignissen ersetzt werden, jetzt oder in der Zukunft.
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
Wenn Linux gebootet ist, versuchen Sie zum Beispiel:
cd doom
./doom
Die ESI-Toolchain sollte auf jedem Linux-System mit minimalem Aufwand bauen. Wir haben sie auch erfolgreich auf macOS gebaut, mit einigen Modifikationen. Stellen Sie sicher, dass gcc, python3, CMake, ninja, flex, bison installiert und betriebsbereit sind.
Beginnen Sie im ausgecheckten eternal-Ordner.
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
Geben Sie exit ein, wenn Sie fertig sind, um die VM zu beenden.
Standard-Workflow für Cross-Kompilierung. Für einen schnellen Einstieg stellen wir ein praktisches Skript (clang_userspace.sh) bereit, das die Umgebung einrichtet und clang aufruft.
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
Dann das initramfs und die Kapsel neu bauen:
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
Die VM booten:
./vm/vm linux/vmlinux.bootimage
Sobald Linux gebootet ist:
./hello.elf
Bereitgestellt für Entwickler von heute, um die Architektur und die Toolchain zu verstehen. Nichts davon (außer der Serviette) ist für jemanden in 1.000 Jahren notwendig, um eine Kapsel wiederzubeleben und die darin enthaltene Software auszuführen.
Wenn Sie die ESI-VM auf eine neue Plattform portiert haben, teilen Sie uns dies bitte über ein Issue mit, und wir werden es zu dieser Liste hinzufügen.
Eine minifizierte Version der ESI-VM (in 366 Bytes C) war ein Gewinner des 29. IOCCC-Wettbewerbs.