
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 Wurzel-Repository für die Eternal Software Initiative.
Die ESI definiert eine minimale Maschinenarchitektur (basierend auf einer Modifikation des 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 Port von Linux, Ports der C/C++-Laufzeitbibliotheken und andere Werkzeuge (einschließlich einer Referenzimplementierung einer virtuellen Maschine in ~50 Zeilen C), die benötigt werden, um aus vorhandener Software eine in sich geschlossene „Kapsel" zu bauen und auszuführen.
Was ist der Sinn all dessen? Die Ausführung heutiger Software erfordert einen komplexen Abhängigkeitsstapel (Compiler, Bibliotheken, Frameworks, Betriebssystem) auf proprietärer und unvollständig dokumentierter Hardware, was es sehr schwierig macht, sicherzustellen, dass heutige Software auch in Zukunft weiterhin funktioniert. Dieses Problem des „Bit-Rot" ist jedem bekannt, der Legacy-Software über einen Zeitraum von Jahren oder Jahrzehnten wartet, aber stellen Sie sich nun einen Historiker in 1.000 Jahren vor, der versucht, das Leben im 21. Jahrhundert zu verstehen, das zu einem großen Teil durch Software erfahren wird. Selbst wenn die heutigen Software-Binärdateien erhalten bleiben, ist es weit hergeholt anzunehmen, dass diese Binärdateien noch ausführbar sein werden. Emulatoren wie QEMU verschieben dieses Problem, lösen es aber nicht: Auch sie haben einen ähnlich komplexen Stapel von Software- und Hardware-Abhä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 leistungsfähig genug, um jede Software effizient darzustellen, und die kein Wissen über proprietäre Hardware, Software, Frameworks und so weiter erfordert, und (2) eine Toolchain implementiert, um jede vorhandene Software in eine in sich geschlossene „Kapsel" für diese Architektur zu kompilieren. Dies stellt sicher, dass die Software – vorausgesetzt, die Kapsel-Binärdatei und die Servietten-Anweisungen bleiben erhalten – in ferner Zukunft wiederbelebt und erfahren werden kann, ohne Kenntnisse über heutige Computersysteme vorauszusetzen.
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 erstellen.
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 von 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 weiteren Abhängigkeiten. SDL3 kann leicht durch jedes andere Mittel 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 hat, versuchen Sie zum Beispiel:
cd doom
./doom
Die ESI-Toolchain sollte sich mit minimalem Aufwand auf jedem Linux-System bauen lassen. Wir haben sie auch erfolgreich auf macOS gebaut, mit einigen Modifikationen. Stellen Sie sicher, dass gcc, python3, CMake, ninja, flex, bison installiert und funktionsfähig sind.
Beginnen Sie im ausgecheckten Ordner 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
Geben Sie exit ein, wenn Sie fertig sind, um die VM zu beenden.
Standard-Cross-Compilation-Workflow. Um schnell loszulegen, stellen wir ein Komfortskript (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
Bauen Sie dann das initramfs und die Kapsel neu:
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
Starten Sie die VM:
./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) wird von jemandem in 1.000 Jahren benötigt, um eine Kapsel wiederzubeleben und die darin enthaltene Software auszuführen.