برنامه نویسی

Cross-Compliling Haskell تحت Nixos با Docker

من یاد گرفتم که چگونه پروژه های Haskell را به صورت متقاطع تحت NIXOS با استفاده از تصاویر Docker برای معماری ARM و نحوه اجرای آنها تحت عنوان تقلید بر روی x86_64 میزبان

انگیزه

من در اجلاس AWS 2025 در سنگاپور شرکت کردم. من از این رویداد لذت بردم غرفه هایی از شرکت های مختلف وجود داشت که من جالب دیدم ، مانند Gitlab و Clickhouse. مهمتر از همه ، من با افراد بسیار جالبی ملاقات کردم.

در میان غرفه ها ، مورد خاصی وجود داشت که توجه من را به خود جلب کرد: AWS در حال نمایش پردازنده های Graviton مبتنی بر بازوی آنها بود. من با افراد AWS گپ زدم و چند سؤال پرسیدم که مدتی در ذهن داشتم.

من تعدادی از پروژه های Haskell خود را در Raspberry Pi 4 که مبتنی بر معماری بازو است ، گردآوری کردم. من کنجکاو بودم که ببینم برخی دیگر بر روی پردازنده های Graviton عملکرد می کنند. من می توانم بروم و آنها را در پردازنده های Graviton ، در Raspberry Pi 4 خود ، یا به اصطلاح آنها را به طور متقاطع در من کامپایل کنم x86_64 ایستگاه کاری

پروژه های HASKELL متقاطع

پروژه های HASKELL متقابل همواره برای من ارعاب کننده به نظر می رسید. من نمی دانم که آیا این امکان پذیر است. حتی پیوند دادن به صورت آماری باینری هاسکل کاملاً یک چالش است ، به خصوص تحت NIX. درعوض ، من در حال حاضر به صورت آماری پروژه های Haskell خود را تحت یک تصویر Docker که توسط Benz0Li ساخته و منتشر شده است ، تالیف می کنم:

https://github.com/benz0li/ghc-musl

من از یک اسکریپت استفاده می کنم که تولید می کند cabal.project.freeze از راه اندازی NIX من ، پروژه را درون یک ظرف Docker از تصویر فوق کامپایل می کند ، باینری را به میزبان کپی می کند و سپس با استفاده از UPX آن را فشرده می کند.

می توانید اسکریپت را در زیر مخزن الگوی پروژه Haskell من بررسی کنید.

من می دانستم که Benz0li تصاویر Docker را برای هر دو منتشر می کند x86_64 وت arm64 معماری وی حتی اخیراً تصاویر اضافی را برای مقابله با محدودیت های مجوز GMP منتشر کرده است.

بنابراین من تصمیم گرفتم که تصویر Docker مبتنی بر بازو را روی خود اجرا کنم x86_64 میزبان ، که قبلاً هرگز امتحان نکرده بودم. اول ، من باید اطمینان حاصل کنم که می توانم این کار را انجام دهم. این دعوت طبیعی ظرف Docker است:

$ docker run --rm quay.io/benz0li/ghc-musl:9.8.4 uname -a
Linux 8c14a21fc636 6.12.30 #1-NixOS SMP PREEMPT_DYNAMIC Thu May 22 12:29:54 UTC 2025 x86_64 Linux
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

همانطور که انتظار می رفت ، uname -a فرمان در داخل ظرف نشان می دهد که در حال اجرا است x86_64 معماری اکنون ، ما می توانیم سعی کنیم تصویر Docker مبتنی بر بازو را اجرا کنیم:

$ docker run --rm --platform linux/arm64 quay.io/benz0li/ghc-musl:9.8.4 uname -a
# exec /usr/bin/uname: exec format error
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

پیکربندی پشتیبانی QEMU در Nixos

انتظار می رود: ما نمی توانیم یک تصویر docker مبتنی بر بازو را روی یک اجرا کنیم x86_64 میزبان بدون برخی از تنظیمات اضافی ، به ویژه ، با استفاده از QEMU.

بیشتر آموزش هایی که من به صورت آنلاین پیدا کردم با استفاده از:

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

… که تصمیم گرفتم روی میزبان Nixos خود کار نکند. درعوض ، من از گزینه Nixos برای فعال کردن تقلید QEMU استفاده کردم:

{
    boot.binfmt = {
      emulatedSystems = [ "aarch64-linux" ];
    };
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این هم کار نکرد. ظاهراً داکر به باینری های استاتیک ارائه شده توسط multiarch/qemu-user-static تصویر بنابراین من پیکربندی خود را مطابق توصیه تغییر دادم:

{
    boot.binfmt = {
      emulatedSystems = [ "aarch64-linux" ];
      preferStaticEmulators = true; # Make it work with Docker
    };
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

خبر خوب

و به همین ترتیب کار کرد:

$ docker run --rm --platform linux/arm64 quay.io/benz0li/ghc-musl:9.8.4 uname -a
Linux 15afb3b1a45b 6.12.30 #1-NixOS SMP PREEMPT_DYNAMIC Thu May 22 12:29:54 UTC 2025 aarch64 Linux
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اکنون ، من می توانم فیلمنامه را برای مصرف استدلال های دلخواه تغییر دهم و آنها را به docker run دستور:

bash build-static.sh --platform=linux/arm64
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

راستش ، من انتظار نداشتم که کار کند ، اما این کار را انجام داد ، اگرچه به طرز چشمگیری کندتر بود! یک چیزی که من متوجه شدم این بود که هر دو را اجرا کنم x86_64 وت arm64 باینری ها روی من x86_64 میزبان ، که من اصلاً انتظار آن را نداشتم. ظاهرا ، سیستم من اکنون قادر به اجرای هر دو معماری به طور همزمان است – با دومی که تحت تقلید قرار دارد.

می توانید اسکریپت را بررسی کرده و آن را برای پروژه های Haskell خود اتخاذ کنید.

پایان

روز جالبی بود.

اولا ، من یک غیرx86_64 تصویر docker تحت تقلید در من x86_64 میزبان ، که من قبلاً هرگز انجام نداده بودم. ثانیا ، اکنون می دانم که می توانم پروژه های Haskell خود را برای معماری های بازو با استفاده از arm64 تصویر Docker ارائه شده توسط BENZ0LI. با پیشروی ، من می توانم بدون ترس از پروژه های Haskell برای هر معماری پشتیبانی شده و غیر بومی استفاده کنم.

و من مطمئناً می خواهم پردازنده های Graviton را امتحان کنم ، به محض اینکه یک نمونه Graviton EC2 را در AWS بچرخانم.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا