
최소한의 머신 아키텍처와 LLVM 컴파일러 백엔드, Linux 포트, 복잡한 종속성 없이 무기한 실행 가능한 자체 포함 소프트웨어 캡슐을 생성하기 위한 가상 머신을 갖춘 설계.
이 저장소는 이터널 소프트웨어 이니셔티브(Eternal Software Initiative)의 루트 저장소입니다.
ESI는 (Subleq OISC의 변형을 기반으로 한) 최소 머신 아키텍처를 정의하며, 그 단순성 덕분에 완전한 명세를 냅킨에 적어 둘 수 있습니다. 그런 다음 이 아키텍처를 위한 LLVM 컴파일러 백엔드, Linux 포트, C/C++ 런타임 라이브러리 포트, 그리고 기존 소프트웨어로부터 자체 포함된 '캡슐'을 빌드하고 실행하는 데 필요한 기타 도구(C로 약 50줄로 작성된 참조 가상 머신 구현 포함)를 제공합니다.
이 모든 것의 요점은 무엇일까요? 오늘날의 소프트웨어를 실행하려면 독점적이고 불완전하게 문서화된 하드웨어 위에 복잡한 의존성 스택(컴파일러, 라이브러리, 프레임워크, OS)이 필요하므로, 오늘날의 소프트웨어가 미래에도 계속 작동할 것이라고 보장하기가 매우 어렵습니다. 이 '비트 부패(bit rot)' 문제는 수년 또는 수십 년에 걸쳐 레거시 소프트웨어를 유지 관리하는 모든 사람에게 잘 알려져 있습니다. 하지만 이제 1,000년 후의 역사가가 대부분 소프트웨어를 통해 경험되는 21세기 생활을 이해하려 한다고 상상해 보십시오. 오늘날의 소프트웨어 바이너리가 보존되더라도 그 바이너리가 여전히 실행 가능할 것이라고 상상하기는 어렵습니다. QEMU와 같은 에뮬레이터는 이 문제를 다른 곳으로 옮길 뿐 해결하지는 못합니다. 이들 역시 비슷하게 복잡한 소프트웨어 및 하드웨어 의존성 스택을 가지고 있으므로 머지않은 미래에도 실행 가능하지 않을 것입니다.
ESI는 (1) 냅킨에 적어 둘 수 있을 정도로 단순하면서도 모든 소프트웨어를 효율적으로 표현할 수 있을 만큼 강력하고, 독점 하드웨어, 소프트웨어, 프레임워크 등에 대한 지식을 필요로 하지 않는 아키텍처를 정의하고, (2) 기존 소프트웨어를 이 아키텍처를 위한 자체 포함된 '캡슐'로 컴파일하는 툴체인을 구현함으로써 이 문제를 해결합니다. 이는 캡슐 바이너리와 냅킨 지침이 보존된다면, 현재의 컴퓨팅 시스템에 대한 어떤 지식도 가정하지 않고 먼 미래에 소프트웨어를 복원하고 경험할 수 있도록 보장합니다.
이 저장소에는 ESI 머신을 직접 빌드하고 실행하고, 기존 소프트웨어에서 ESI '캡슐'을 빌드하는 데 필요한 모든 것이 포함되어 있습니다.
ESI의 사명에 대한 자세한 내용은 다음을 참조하십시오: https://www.eternal-software.org
이 저장소에는 서브모듈로 ESI 포크 버전의 LLVM 툴체인, Linux 커널, uClibc-ng, 그리고 Busybox가 포함되어 있습니다. 이들은 모두 함께 체크아웃되어야 합니다.
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년 후의 누군가가 캡슐을 복원하고 그 안의 소프트웨어를 실행하는 데 필요하지 않습니다.
ESI 가상 머신을 새 플랫폼으로 포팅하셨다면 이슈를 제출하여 알려 주십시오. 이 목록에 추가하겠습니다.
ESI 가상 머신의 축소 버전(C로 366바이트)은 제29회 IOCCC 대회의 수상작이었습니다.