
Architettura di macchina minimale con backend compilatore LLVM, porting Linux e macchina virtuale per creare capsule software autonome che rimangono eseguibili indefinitamente senza dipendenze complesse.
Questo è il repository principale per la Eternal Software Initiative.
L'ESI definisce un'architettura macchina minima (basata su una modifica del Subleq OISC) così semplice che la sua specifica completa può essere scritta su un tovagliolo. Forniamo quindi un backend compilatore LLVM per questa architettura, una porta di Linux, porte delle librerie runtime C/C++ e altri strumenti (inclusa un'implementazione di macchina virtuale di riferimento in circa 50 righe di C) necessari per costruire ed eseguire una 'capsula' autonoma dal software esistente.
Qual è lo scopo di tutto ciò? Eseguire il software odierno richiede uno stack complesso di dipendenze (compilatori, librerie, framework, sistemi operativi) su hardware proprietario e documentato in modo incompleto, rendendo molto difficile garantire che il software odierno continui a funzionare in futuro. Questo problema del 'bit rot' è ben noto a chiunque mantenga software legacy per anni o decenni, ma ora immaginate uno storico tra 1.000 anni che cerca di capire la vita del XXI secolo, gran parte della quale è vissuta attraverso il software. Anche se i binari del software odierno fossero conservati, è fantasioso immaginare che quei binari siano ancora eseguibili. Emulatori come QEMU spostano questo problema ma non lo risolvono: anch'essi hanno uno stack di dipendenze software e hardware altrettanto complesso, e quindi non saranno eseguibili in un lontano futuro.
L'ESI risolve questo problema (1) definendo un'architettura sufficientemente semplice da scrivere su un tovagliolo ma abbastanza potente da rappresentare efficientemente qualsiasi software, senza richiedere la conoscenza di hardware, software, framework proprietari e così via, e (2) implementando una toolchain per compilare qualsiasi software esistente in una 'capsula' autonoma per questa architettura. Ciò garantisce che, a patto che il binario della capsula e le istruzioni sul tovagliolo siano conservati, il software possa essere resuscitato e sperimentato nel lontano futuro senza assumere alcuna conoscenza degli attuali sistemi informatici.
Questo repository include tutto il necessario per costruire ed eseguire la propria macchina ESI e per costruire 'capsule' ESI dal software esistente.
Per maggiori informazioni sulla missione dell'ESI, visita: https://www.eternal-software.org
Questo repository include, come sottomoduli, fork ESI della toolchain LLVM, del kernel Linux, di uClibc-ng e di Busybox. Tutti questi devono essere prelevati insieme.
git clone --recurse-submodules https://github.com/adriancable/eternal
Avrai bisogno di SDL3 per costruire la macchina virtuale ESI. Installa con ad esempio apt install libsdl3-dev. Non ci sono altre dipendenze. SDL3 può essere facilmente sostituito con qualsiasi altro mezzo per scrivere pixel e catturare eventi da tastiera, ora o in futuro.
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
Quando Linux è avviato, prova ad esempio:
cd doom
./doom
La toolchain ESI dovrebbe compilarsi su qualsiasi sistema Linux con il minimo sforzo. Abbiamo anche compilato con successo su macOS, con alcune modifiche. Assicurati di avere gcc, python3, CMake, ninja, flex, bison installati e funzionanti.
Inizia nella cartella eternal prelevata.
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
Digita exit quando hai finito per terminare la VM.
Flusso di lavoro standard di cross-compilazione. Per iniziare velocemente, forniamo uno script di comodità (clang_userspace.sh) che configura l'ambiente e chiama 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
Poi ricostruisci l'initramfs e la capsula:
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
Avvia la VM:
./vm/vm linux/vmlinux.bootimage
Una volta che Linux è avviato:
./hello.elf
Fornita per gli sviluppatori di oggi per comprendere l'architettura e la toolchain. Niente di tutto questo (eccetto il tovagliolo) è necessario per qualcuno tra 1.000 anni per resuscitare una capsula ed eseguire il software al suo interno.
Se hai portato la macchina virtuale ESI su una nuova piattaforma, faccelo sapere aprendo un Issue e lo aggiungeremo a questa lista.
Una versione minimizzata della macchina virtuale ESI (in 366 byte di C) è stata vincitrice della 29ª competizione IOCCC.