
معمارية آلة بسيطة مع خلفية مترجم LLVM، ومنفذ لينكس، وآلة افتراضية لإنشاء كبسولات برمجية ذاتية الاحتواء تبقى قابلة للتشغيل إلى أجل غير مسمى دون تبعيات معقدة.
هذا هو المستودع الأساسي لـ مبادرة البرمجيات الأبدية.
تحدد ESI بنية آلة بسيطة (مبنية على تعديل لـ Subleq OISC) بسيطة جدًا لدرجة أن مواصفاتها الكاملة يمكن كتابتها على منديل ورقي. ثم نقدم خلفية مترجم LLVM لهذه البنية، ومنفذًا لنظام Linux، ومنافذ لمكتبات زمن التشغيل C/C++، وأدوات أخرى (بما في ذلك تطبيق آلة افتراضية مرجعي في حوالي 50 سطرًا من C) اللازمة لبناء وتشغيل "كبسولة" ذاتية الاحتواء من البرامج الموجودة.
ما الهدف من كل هذا؟ تشغيل برامج اليوم يتطلب كومة معقدة من التبعيات (مترجمات، مكتبات، أطر عمل، نظام تشغيل) فوق أجهزة مملوكة وغير موثقة بالكامل، مما يجعل من الصعب جدًا ضمان استمرار عمل برامج اليوم في المستقبل. مشكلة "تعفن البتات" هذه معروفة جيدًا لأي شخص يحافظ على برامج قديمة على مدى سنوات أو عقود، لكن تخيل الآن مؤرخًا بعد 1000 عام من الآن يحاول فهم الحياة في القرن الحادي والعشرين، والتي يتم تجربتها كثيرًا من خلال البرامج. حتى إذا تم حفظ ثنائيات برامج اليوم، فمن المستبعد جدًا تخيل أن هذه الثنائيات ستظل قابلة للتشغيل. أدوات المحاكاة مثل 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
ستحتاج إلى SDL3 لبناء الآلة الافتراضية لـ ESI. قم بتثبيته باستخدام على سبيل المثال 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 عند الانتهاء لإنهاء الآلة الافتراضية.
سير عمل التجميع المتقاطع القياسي. للبدء بسرعة، نقدم برنامجًا نصيًا مناسبًا (clang_userspace.sh) يقوم بإعداد البيئة واستدعاء 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
ثم أعد بناء 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 linux/vmlinux.bootimage
بمجرد تشغيل Linux:
./hello.elf
مقدمة لمطوري اليوم لفهم البنية وسلسلة الأدوات. لا شيء من هذا (باستثناء المنديل) ضروري لشخص بعد 1000 عام من الآن لإحياء كبسولة وتشغيل البرنامج بداخلها.
إذا قمت بنقل الآلة الافتراضية لـ ESI إلى منصة جديدة، فيرجى إخبارنا عن طريق تقديم Issue وسنضيفها إلى هذه القائمة.
فازت نسخة مصغرة من الآلة الافتراضية لـ ESI (في 366 بايت من C) بمسابقة IOCCC التاسعة والعشرين.