
Arquitetura de máquina minimalista com backend de compilador LLVM, porta Linux e máquina virtual para criar cápsulas de software autocontidas que permanecem executáveis indefinidamente sem dependências complexas.
Este é o repositório raiz da Eternal Software Initiative.
A ESI define uma arquitetura de máquina mínima (baseada numa modificação do Subleq OISC) que é tão simples que a sua especificação completa pode ser escrita num guardanapo. Fornecemos depois um backend de compilador LLVM para esta arquitetura, um port do Linux, ports das bibliotecas de runtime C/C++, e outras ferramentas (incluindo uma implementação de máquina virtual de referência em ~50 linhas de C) necessárias para compilar e executar uma 'cápsula' autocontida a partir de software existente.
Qual é o objetivo de tudo isto? Executar o software de hoje requer uma pilha complexa de dependências (compiladores, bibliotecas, frameworks, SO) sobre hardware proprietário e incompletamente documentado, tornando muito difícil garantir que o software de hoje continuará a funcionar no futuro. Este problema de 'bit rot' é bem conhecido por qualquer pessoa que mantenha software legado ao longo de anos ou décadas, mas agora imagine um historiador daqui a 1.000 anos a tentar compreender a vida do século XXI, grande parte da qual é vivida através de software. Mesmo que os binários do software de hoje sejam preservados, é rebuscado imaginar que esses binários ainda serão executáveis. Emuladores como o QEMU contornam este problema mas não o resolvem: também eles têm uma pilha igualmente complexa de dependências de software e hardware, e por isso também não serão executáveis num futuro distante.
A ESI resolve este problema ao (1) definir uma arquitetura que é suficientemente simples para ser escrita num guardanapo mas suficientemente poderosa para representar eficientemente qualquer software, e que não requer conhecimento de qualquer hardware, software, framework proprietário, etc., e (2) implementar uma toolchain para compilar qualquer software existente numa 'cápsula' autocontida para esta arquitetura. Isto garante que, desde que o binário da cápsula e as instruções do guardanapo sejam preservados, o software pode ser revivido e experienciado num futuro distante sem assumir qualquer conhecimento dos sistemas informáticos atuais.
Este repositório inclui tudo o que é necessário para compilar e executar a sua própria máquina ESI, e compilar 'cápsulas' ESI a partir de software existente.
Para mais informações sobre a missão da ESI, consulte: https://www.eternal-software.org
Este repositório inclui, como submódulos, forks ESI da toolchain LLVM, do kernel Linux, do uClibc-ng e do Busybox. Todos estes devem ser obtidos em conjunto.
git clone --recurse-submodules https://github.com/adriancable/eternal
Vai precisar do SDL3 para compilar a máquina virtual ESI. Instale com, por exemplo, apt install libsdl3-dev. Não há outras dependências. O SDL3 pode facilmente ser substituído por qualquer outro meio para escrever píxeis e capturar eventos de teclado, agora ou no futuro.
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
Quando o Linux tiver arrancado, experimente por exemplo:
cd doom
./doom
A toolchain ESI deve compilar em qualquer sistema Linux com esforço mínimo. Também compilámos com sucesso em macOS, com algumas modificações. Certifique-se de que tem gcc, python3, CMake, ninja, flex, bison instalados e operacionais.
Comece na pasta eternal obtida.
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
Escreva exit quando terminar para encerrar a VM.
Fluxo de trabalho padrão de compilação cruzada. Para começar rapidamente, fornecemos um script de conveniência (clang_userspace.sh) que configura o ambiente e chama o 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
Depois recompile o initramfs e a cápsula:
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
Arranque a VM:
./vm/vm linux/vmlinux.bootimage
Depois de o Linux ter arrancado:
./hello.elf
Fornecida para que os programadores de hoje compreendam a arquitetura e a toolchain. Nada disto (exceto o guardanapo) é necessário para que alguém daqui a 1.000 anos reviva uma cápsula e execute o software que contém.