
최소한의 머신 아키텍처와 LLVM 컴파일러 백엔드, Linux 포트, 복잡한 종속성 없이 무기한 실행 가능한 자체 포함 소프트웨어 캡슐을 생성하기 위한 가상 머신을 갖춘 설계.
이것은 Eternal Software Initiative의 루트 저장소입니다.
ESI는 (Subleq OISC의 변형을 기반으로 한) 최소한의 기계 아키텍처를 정의하는데, 이는 너무 단순해서 전체 명세를 냅킨에 적을 수 있을 정도입니다. 그런 다음 이 아키텍처를 위한 LLVM 컴파일러 백엔드, Linux 포팅, C/C++ 런타임 라이브러리 포팅, 그리고 기존 소프트웨어로부터 자체 포함된 '캡슐'을 빌드하고 실행하는 데 필요한 기타 도구들(약 50줄의 C로 작성된 참조 가상 머신 구현 포함)을 제공합니다.
이 모든 것의 요점은 무엇일까요? 오늘날의 소프트웨어를 실행하려면 독점적이고 불완전하게 문서화된 하드웨어 위에 복잡한 의존성 스택(컴파일러, 라이브러리, 프레임워크, OS)이 필요하며, 이는 오늘날의 소프트웨어가 미래에도 계속 작동할 것임을 보장하기 매우 어렵게 만듭니다. 이 '비트 부패(bit rot)' 문제는 수년 또는 수십 년에 걸쳐 레거시 소프트웨어를 유지보수하는 사람이라면 누구나 잘 알고 있지만, 이제 1,000년 후의 역사학자가 21세기 삶을 이해하려 한다고 상상해 보십시오. 그 삶의 상당 부분은 소프트웨어를 통해 경험됩니다. 오늘날의 소프트웨어 바이너리가 보존된다 하더라도, 그 바이너리가 여전히 실행 가능할 것이라고 상상하기는 어렵습니다. QEMU와 같은 에뮬레이터는 이 문제를 다른 곳으로 옮길 뿐 해결하지 못합니다. 그것들 역시 마찬가지로 복잡한 소프트웨어 및 하드웨어 의존성 스택을 가지고 있어서, 먼 미래에는 실행될 수 없을 것입니다.
ESI는 이 문제를 (1) 냅킨에 적을 수 있을 만큼 단순하지만 어떤 소프트웨어든 효율적으로 표현할 수 있을 만큼 강력하고, 독점 하드웨어, 소프트웨어, 프레임워크 등에 대한 지식을 요구하지 않는 아키텍처를 정의하고, (2) 기존 소프트웨어를 이 아키텍처를 위한 자체 포함된 '캡슐'로 컴파일하는 툴체인을 구현함으로써 해결합니다. 이는 캡슐 바이너리와 냅킨 명세만 보존된다면, 현재의 컴퓨팅 시스템에 대한 어떤 지식도 가정하지 않고 먼 미래에 소프트웨어를 되살려 경험할 수 있음을 보장합니다.
이 저장소에는 자신만의 ESI 머신을 빌드하고 실행하며, 기존 소프트웨어로부터 ESI '캡슐'을 빌드하는 데 필요한 모든 것이 포함되어 있습니다.
ESI의 사명에 대한 더 많은 정보는 다음을 참조하십시오: https://www.eternal-software.org
이 저장소는 LLVM 툴체인, Linux 커널, uClibc-ng, Busybox의 ESI 포크를 서브모듈로 포함합니다. 이들은 모두 함께 체크아웃되어야 합니다.
git clone --recurse-submodules https://github.com/adriancable/eternal
ESI 가상 머신을 빌드하려면 SDL3가 필요합니다. 예를 들어 apt install libsdl3-dev로 설치하십시오. 다른 의존성은 없습니다. SDL3는 현재나 미래에 픽셀을 쓰고 키보드 이벤트를 캡처하는 다른 어떤 수단으로도 쉽게 대체될 수 있습니다.
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
Linux가 부팅되면, 예를 들어 다음을 시도해 보십시오:
cd doom
./doom
ESI 툴체인은 최소한의 노력으로 어떤 Linux 시스템에서든 빌드되어야 합니다. 우리는 약간의 수정을 통해 macOS에서도 성공적으로 빌드했습니다. gcc, python3, CMake, ninja, flex, bison이 설치되어 작동하는지 확인하십시오.
체크아웃된 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
완료되면 exit를 입력하여 VM을 종료하십시오.
표준 크로스 컴파일 워크플로우입니다. 빠르게 시작할 수 있도록, 환경을 설정하고 clang을 호출하는 편의 스크립트(clang_userspace.sh)를 제공합니다.
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
그런 다음 initramfs와 캡슐을 다시 빌드하십시오:
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
VM을 부팅하십시오:
./vm/vm linux/vmlinux.bootimage
Linux가 부팅되면:
./hello.elf
오늘날의 개발자들이 아키텍처와 툴체인을 이해할 수 있도록 제공됩니다. 1,000년 후의 누군가가 캡슐을 되살리고 그 안의 소프트웨어를 실행하는 데에는 (냅킨을 제외하고) 이 중 어느 것도 필요하지 않습니다.
make는 튜링 완전하므로 Subleq VM을 실행할 수 있습니다ESI 가상 머신을 새로운 플랫폼으로 포팅하셨다면, Issue를 제출하여 알려주시면 이 목록에 추가하겠습니다.
ESI 가상 머신의 축소 버전(366바이트의 C)이 제29회 IOCCC 대회의 우승작이었습니다.