تصور کنید میخواهید مدرنترین زبان برنامهنویسی جهان را روی تراشههایی اجرا کنید که پیش از تولد شما ساخته شدهاند. اکنون با ظهور ابزار Cilly، این رویای مهندسی به واقعیت تبدیل شده و Rust را از وابستگی مطلق به زیرساختهای پیچیده نجات داده است.
به نقل از مستندات پروژه، این ابزار توانسته است کامپایلر rustc را به ۴۶ میلیون خط کد C ترجمه کند. این حجم عظیم از کد، در واقع پلی است برای اجرای Rust روی سختافزارهایی که پیشتر «منسوخ» تلقی میشدند. پروژهای که با نام crustc در گیتهاب میزبانی میشود، یک کامپایلر کاربردی است که کاملاً با GCC و make ساخته شده و بر اساس بیلد نایتلای ۱۶ ژوئن ۲۰۲۶ (نسخه v1.98.0، کامیت c712ea946) اجرا میشود.
برای سالها، وابستگی شدید Rust به LLVM (یک زیرساخت بهینهساز کد) مانند دیواری بلند بود که توسعهدهندگان را از سیستمهای قدیمی جدا میکرد. اگر سختافزاری بکاند LLVM نداشت، Rust عملاً روی آن قابل اجرا نبود. همانطور که در تحلیلهای پیشین ما دربارهی اکوسیستم زبانهای برنامهنویسی اشاره کردیم، این موضوع همواره نقطه ضعف اصلی Rust در مقایسه با زبان C ذکر میشد؛ چراکه کامپایلرهای C حتی در تاریکترین و قدیمیترین گوشههای سختافزاری دنیا و روی مبهمترین پلتفرمها هم حضور دارند. هدف بنیادین این پروژه، حذف کامل این مشکل است تا کاربران بتوانند هر کامپایلر C مورد نیاز خود را برای یک هدف (Target) خاص تعریف کنند.
سازوکار Cilly
قلب تپنده این دستاورد، ابزار Cilly است که پس از ۱۴ تلاش ناموفق توسعهدهندهاش برای حل مسئله کامپایل Rust به C به ثمر رسیده است. این مسیر شامل چندین تلاش عمومی و خصوصی پیشین، از جمله پروژه rustc_codegen_clr بود. Cilly در واقع یک کتابخانه Rust برای تولید کد C است که به عنوان یک پلاگین برای بکاند کامپایلر عمل کرده و این ترجمه را ممکن میسازد.
تفاوت کلیدی Cilly با تلاشهای قبلی در این است که محیط هدف را ثابت نمیبیند. در عوض، خود را با هر کامپایلر C و هر پلتفرمی که با آن روبرو شود، تطبیق میدهد. این ابزار به گونهای طراحی شده است که حتی یک «کامپایلر C شمینکی برای سیستمعامل Blorbo» را نیز راضی کند؛ و این کار را از طریق استعلام ویژگیهای خاص محیط انجام میدهد.
برای رسیدن به این انعطافپذیری، Cilly برنامههای «شاهد» (Witness) تولید میکند تا قابلیتهای کامپایلر میزبان را بسنجد. برای مثال، قطعات کوچکی از کد مینویسد تا بررسی کند آیا کامپایلر از _Thread_local پشتیبانی میکند یا خیر؛ این کار با بررسی کدی شبیه به _Thread_local int KEYWORD_TLS_SUPPORTED; انجام میشود. همچنین با استفاده از دستور assert(sizeof(float) == sizeof(double)); بررسی میکند که آیا اندازه دادههای اعشاری (float و double) در آن پلتفرم یکسان است یا نه.
این ابزار موارد زیر را در پلتفرم هدف استعلام و تطبیق میدهد:
- تمام چیدمانها (Layouts)، اندازهها و ترازهای نوع داده (Type Alignments).
- رمزگذاریهای نویسه (بهویژه ASCII).
- فرمتهای اعداد صحیح (complement دو یا Two's complement).
اگر ویژگیای در پلتفرم هدف نباشد، Cilly سعی میکند راهکارهای جایگزین (Fallbacks) را پیاده کند. هدف توسعهدهنده، انطباق سختگیرانه با استاندارد ANSI C است، که شامل راهکارهای جایگزین برای مشکلاتی در استانداردهای مدرن C، مانند «تخصیص نام مستعار سختگیرانه» (Strict Aliasing) میشود. با این حال، این بدان معناست که خروجی نهایی کاملاً وابسته به کامپایلر است؛ یعنی کد C تولید شده برای Arm64 روی riscv32 اجرا نمیشود، هرچند تولید یک خروجی مجزا برای riscv32 امکانپذیر است.
مدیریت مقیاس و حجم کد
حجم خروجی این فرآیند خیرهکننده است. ترجمه rustc نسخه ۱.۹۸.۰-nightly منجر به تولید ۴۶ میلیون خط کد C شد (و تعدادی Wrapperهای C++ برای LLVM که برای در دسترس قرار دادن تنظیمات خاص LLVM استفاده شدهاند). با این حال، طبق گزارش توسعهدهنده، ساخت (Build) این پروژه بدون بهینهسازی، روی یک ایستگاه کاری لینوکس ARM64 تنها چند دقیقه زمان میبرد.
در آزمایشهای ثبت شده با دستور make -j20:
- زمان کاربر (user): ۹۳۷.۹۸ ثانیه
- زمان سیستم (system): ۱۲۳.۷۷ ثانیه
- استفاده از CPU: ۱۳۵۲٪
- زمان کل: ۱ ساعت و ۱۸ دقیقه و ۴۸ ثانیه
به دلیل اینکه بهینهسازیهای سنگین ممکن است باعث شکست در فرآیند ساخت شود یا باعث شود کامپایلر در مواجهه با فایلهای غولپیکر Rust «خفه شود»، شدیداً توصیه شده است که بهینهسازیها غیرفعال باشند.
مشخصات فنی دقیق بیلد:
- کامپایلر C: GCC 13.3.0 (Ubuntu 24.04.1).
- لینکر: Ubuntu LLD 18.1.3.
- سیستمعامل: Linux spark-2773 6.17.0-1021-nvidia (aarch64).
- وابستگی: نیاز به فایل
libLLVM.so.22.1-rust-1.98.0-nightly. کاربر باید مسیرLLVM_LIB_DIRرا ارائه دهد، مثلاً:~/.rustup/toolchains/nightly-2026-06-16-aarch64-unknown-linux-gnu/lib.
حل پارادوکس بوتاسترپ
یکی از نوآوریهای Cilly، شفافیت شبکه است. این ابزار میتواند از طریق پروتکل TCP یا حتی UART با کامپایلرهای C ارتباط برقرار کند. این ویژگی «پارادوکس بوتاسترپ» را برای پلتفرمهایی که فاقد کامپایلر متقاطع (Cross-compiler) هستند، حل میکند.
در این گردشکار، توسعهدهنده یک سرور C کوچک روی سیستمعامل هدف (مثلاً Blorbo OS) اجرا میکند و rustc را روی یک ماشین لینوکسی استاندارد میراند. سپس Cilly از طریق شبکه دستورات را میفرستد تا کامپایل را انجام دهد. این روش با موفقیت برای کامپایل برنامههای Rust برای ماشینهای مجازی x86 Plan9 از روی میزبان Arm64 لینوکس آزمایش شد. باینریهای حاصل از طریق ابزار nm تأیید شدند و حضور نماد rust_begin_unwind در آنها مشاهده شد (به عنوان مثال: 1020 T _RNvCshfEkAwg4zv6_7___rustc17rust_begin_unwind).
قابلیتهای مدیریتی پیشرفته دیگر:
- تولید Makefile: Cilly میتواند نشانگرهایی (Markers) را در فایلهای آبجکت جاسازی کرده و IR را در یک پوشه کش ذخیره کند. سپس این نشانگرها را میخواند تا توابع و متغیرهای جهانی را بر اساس مکان تعریفشان تقسیم کرده و مجموعهای از Makefileها را تولید کند.
- سفارشیسازی هدف: کاربران میتوانند اهداف را در قالب JSON تعریف کنند و در آن فایل اجرایی محلی (مثلاً
/usr/bin/sdcc) و آرگومانهای پایه (مثلاً-mz180یا--std-c89یا-c) را مشخص کنند.
محدودیتها و شکافهای ABI
این پروژه فعلا یک «نمایش کوتاه» (Teaser) است و هنوز برای مصرف عمومی آماده نشده است. توسعهدهنده این ابزار را «ناپخته» توصیف کرده و به چندین مانع حیاتی اشاره کرده است:
- سازگاری ABI: اگرچه سیستم تا حد زیادی سازگار است، اما شکافهایی در پلتفرمهایی مثل Arm64 وجود دارد. بهطور مشخص، rustc از اشارهگرهای بازگشتی استراکچر (
sret) استفاده میکند که C نمیتواند بهطور بومی آنها را نمایش دهد. در حالی که Arm64 اغلب این مورد را با پاس دادن اشارهگر در همان رجیسترِ اولین آرگومان مدیریت میکند، اما این کار را برای استراکچرهای کوچک (کمتر از ۱۶ بایت) انجام نمیدهد و این موضوع باعث بروز مشکل میشود. - خطاهای مسیردهی: به دلیل دلایل عجیب در استانداردسازی مسیرها (Path-canonicalization)،
crustcاگر در همان دایرکتوری که بیلد شده (ریشه مخزن) اجرا شود، ممکن است کرش کند. این برنامه زمانی به طور عادی کار میکند که از مکانهای دیگر اجرا شود. - کتابخانه استاندارد: کاربران باید کتابخانه
stdرا بهصورت جداگانه بیلد کنند تا بتوانند برنامهها را کامپایل کنند. تلاش برای اجرایmain.rsبدون نصب هدف (Target)، منجر به خطایE0463(عدم یافتن crate برایstd) میشود.
با وجود این باگها و عدم دسترسی فعلی توسعهدهنده به دلیل تعهدات دانشگاهی و آسیب دیدن دستش در اثر یک حادثه با نرمافزار Blender، اثبات مفهوم (Proof-of-Concept) کامل شده است. تبدیل Rust به C در واقع استدلالهای سختافزاری علیه Rust را از بین میبرد. با تبدیل C به یک «زبان اسمبلی قابل حمل»، ایمنی و ارگونومی Rust حالا میتواند به هر تراشهای برسد که یک کامپایلر ساده C دارد.
معنای این اتفاق برای دنیای برنامهنویسی، جداسازی Rust از انحصار LLVM است. در حالی که LLVM بهینهسازیهای فوقالعادهای ارائه میدهد، توانایی هدف قرار دادن یک «کامپایلر C شمینکی برای سیستمعامل Blorbo»، راه را برای ورود Rust به عمیقترین لایههای سیستمهای نهفته (Embedded) و باستانشناسی دیجیتال باز میکند.
گام بعدی شما
- اگر روی سیستمهای قدیمی یا Embedded کار میکنید، مخزن crustc را برای بررسی سازگاری با کامپایلرهای محلی خود دنبال کنید.
- مستندات مربوط به تعریف اهداف (Targets) در قالب JSON را مطالعه کنید تا متوجه شوید چگونه کامپایلر خود را به Cilly معرفی کنید.
- منتظر انتشار نسخههای پایدارتر برای حل مشکل ABI در معماری Arm64 باشید.
اما این تنها بخشی از نبرد برای رهایی از LLVM است؛ برای درک اینکه چرا مدلهای زبانی بزرگ نیز در حال گذار به معماریهای غیرمتمرکز هستند، تحلیل ما درباره لبههای رایانش را بخوانید.




گفتگو