
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 Iniciativa de Software Eterno (Eternal Software Initiative).
A ESI define uma arquitetura mínima de máquina (baseada em uma modificação do OISC Subleq) que é tão simples que sua especificação completa pode ser escrita em um guardanapo. Em seguida, fornecemos um backend de compilador LLVM para essa arquitetura, uma porta do Linux, portas das bibliotecas de tempo de execução C/C++ e outras ferramentas (incluindo uma implementação de máquina virtual de referência em ~50 linhas de C) necessárias para construir e executar uma 'cápsula' autocontida a partir de software existente.
Qual é o propósito de tudo isso? 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. Esse problema de 'podridão de bits' é bem conhecido por qualquer pessoa que mantém software legado ao longo de anos ou décadas, mas agora imagine um historiador daqui a 1.000 anos tentando entender a vida do século XXI, grande parte da qual é vivenciada por meio de software. Mesmo que os binários de software de hoje sejam preservados, é improvável imaginar que esses binários ainda sejam executáveis. Emuladores como QEMU contornam esse problema, mas não o resolvem: eles também possuem uma pilha igualmente complexa de dependências de software e hardware, portanto, também não serão executáveis no futuro distante.
A ESI resolve esse problema (1) definindo uma arquitetura simples o suficiente para escrever em um guardanapo, mas poderosa o suficiente para representar eficientemente qualquer software, sem exigir conhecimento de hardware, software, frameworks, etc., proprietários; e (2) implementando uma cadeia de ferramentas para compilar qualquer software existente em uma 'cápsula' autocontida para essa arquitetura. Isso garante que, desde que o binário da cápsula e as instruções do guardanapo sejam preservados, o software possa ser revivido e vivenciado no futuro distante sem assumir qualquer conhecimento dos sistemas computacionais atuais.
Este repositório inclui tudo o que é necessário para construir e executar sua própria máquina ESI, e construir 'cápsulas' ESI a partir de software existente.
Para mais informações sobre a missão da ESI, veja: https://www.eternal-software.org
Este repositório inclui, como submódulos, forks da ESI da cadeia de ferramentas LLVM, do kernel Linux, do uClibc-ng e do Busybox. Todos devem ser obtidos juntos.
git clone --recurse-submodules https://github.com/adriancable/eternal
Você precisará do SDL3 para construir a máquina virtual ESI. Instale com, por exemplo, apt install libsdl3-dev. Não há outras dependências. O SDL3 pode ser facilmente substituído por qualquer outro meio para escrever pixels 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 inicializado, tente, por exemplo:
cd doom
./doom
A cadeia de ferramentas ESI deve ser construída em qualquer sistema Linux com esforço mínimo. Também construímos com sucesso no macOS, com algumas modificações. Certifique-se de ter gcc, python3, CMake, ninja, flex, bison instalados e operacionais.
Comece na pasta eternal onde o check-out foi feito.
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
Digite 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
Em seguida, reconstrua 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
Inicie a VM:
./vm/vm linux/vmlinux.bootimage
Depois que o Linux iniciar:
./hello.elf
Fornecida para desenvolvedores de hoje entenderem a arquitetura e a cadeia de ferramentas. Nada disso (exceto o guardanapo) é necessário para alguém daqui a 1.000 anos reviver uma cápsula e executar o software nela contido.
Se você portou a máquina virtual ESI para uma nova plataforma, por favor nos avise abrindo uma Issue e nós a adicionaremos a esta lista.
Uma versão minificada da máquina virtual ESI (em 366 bytes de C) foi vencedora da 29ª competição IOCCC.