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 بچرخانم.