
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 della Eternal Software Initiative.
L'ESI definisce un'architettura macchina minimale (basata su una modifica del Subleq OISC) così semplice che la sua specifica completa può essere scritta su un tovagliolo. Forniamo poi un backend del compilatore LLVM per questa architettura, un port di Linux, port delle librerie runtime C/C++ e altri strumenti (inclusa una implementazione di macchina virtuale di riferimento in ~50 righe di C) necessari per compilare ed eseguire una 'capsula' autocontenuta a partire da software esistente.
Qual è il senso di tutto questo? Eseguire il software odierno richiede uno stack complesso di dipendenze (compilatori, librerie, framework, OS) al di sopra di hardware proprietario e documentato in modo incompleto, rendendo molto difficile garantire che il software di oggi continui a funzionare in futuro. Questo problema del 'bit rot' è ben noto a chiunque mantenga software legacy su un arco temporale di anni o decenni, ma ora immaginate uno storico tra 1.000 anni che cerca di comprendere la vita del XXI secolo, gran parte della quale è vissuta attraverso il software. Anche se i binari del software odierno vengono preservati, è azzardato immaginare che quei binari siano ancora eseguibili. Emulatori come QEMU spostano il problema ma non lo risolvono: anch'essi hanno uno stack altrettanto complesso di dipendenze software e hardware, e quindi anch'essi non saranno eseguibili in un futuro remoto.
L'ESI risolve questo problema (1) definendo un'architettura abbastanza semplice da poter essere scritta su un tovagliolo ma abbastanza potente da rappresentare efficientemente qualsiasi software, senza richiedere la conoscenza di alcun hardware, software, framework proprietario e così via, e (2) implementando una toolchain per compilare qualsiasi software esistente in una 'capsula' autocontenuta per questa architettura. Questo garantisce che, a condizione che il binario della capsula e le istruzioni sul tovagliolo siano preservati, il software possa essere riportato in vita e sperimentato in un futuro remoto senza presupporre alcuna conoscenza dei sistemi informatici odierni.
Questo repository include tutto il necessario per compilare ed eseguire la propria macchina ESI, e per compilare 'capsule' ESI a partire da software esistente.
Per maggiori informazioni sulla missione dell'ESI, vedere: https://www.eternal-software.org
Questo repository include, come sottomoduli, i fork ESI della toolchain LLVM, del kernel Linux, di uClibc-ng e di Busybox. Devono essere tutti estratti insieme.
git clone --recurse-submodules https://github.com/adriancable/eternal
Avrai bisogno di SDL3 per compilare 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 è stato avviato, prova ad esempio:
cd doom
./doom
La toolchain ESI dovrebbe compilarsi su qualsiasi sistema Linux con il minimo sforzo. L'abbiamo anche compilata con successo su macOS, con alcune modifiche. Assicurati di avere gcc, python3, CMake, ninja, flex, bison installati e funzionanti.
Inizia dalla cartella eternal appena estratta.
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 al termine per terminare la VM.
Flusso di lavoro standard di cross-compilazione. Per iniziare rapidamente, 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 ricompila 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 avviato Linux:
./hello.elf
Fornita agli sviluppatori di oggi per comprendere l'architettura e la toolchain. Nulla di tutto ciò (tranne il tovagliolo) è necessario affinché qualcuno tra 1.000 anni possa riportare in vita una capsula ed eseguire il software al suo interno.