تخطَّ إلى المحتوى

البناء: meem build

المصدر: docs/build.md في مستودع المجمّع.

نافذة الطرفية
meem build برنامجي.م -o برنامجي
./برنامجي

meem build يترجم البرنامج (وكل ما يستورده) إلى ملف تنفيذي واحد يعمل على جهاز ليس عليه ميم ولا بايثون ولا LLVM. سلوكه سلوك meem برنامجي.م نفسه: المخرجات، الإدخال من stdin، رموز الخروج (0، و3 لخطأ التشغيل)، رسائل أخطاء التشغيل، خطا_قاتل، وخارجي.

المنصات: لينكس x86_64 وحده، وعليه بُني واختُبر. ويندوز وماك غير متاحين في 1.0، لا للتشغيل ولا للبناء.

عدّاد.م
داله مجموع_حتى(ن عدد) عدد:
م = 0
لكل ع في مدى(1, ن + 1):
م += ع
ارجع م
اطبع("مرحبا من ملف تنفيذي")
اطبع("مجموع 1 الى 100: ", مجموع_حتى(100))
مخرجات مسجّلة من المجمّعmeem عدّاد.م · meem 0.10.0+b01b55f
مرحبا من ملف تنفيذيمجموع 1 الى 100: 5050

بُني أيضاً بـ meem build عند بناء الموقع: ملف ساكن حجمه 31.0 ك.ب، شُغّل وحده وطابق مخرجه المخرج أعلاه.

الخيار المعنى
-o ناتج اسم الملف الناتج. الافتراضي: اسم المصدر بلا امتداده، بجواره
--static ربط ساكن: ملف واحد بلا أي اعتماد. الافتراضي حين لا يستعمل البرنامج مكتبة C خارجية
--dynamic ربط حركي بمكتبة C للنظام. يُختار تلقائياً لبرنامج يستعمل عبر خارجي مكتبة C غير libc وlibm
--emit-obj التوقف عند الملف الكائني (ناتج.o) بلا ربط
--target هدف x86_64-linux-musl (ساكن) أو x86_64-linux-gnu (حركي)
--link-arg وسيط وسيط إضافي للرابط؛ يتكرر
(الافتراضي) محسَّن: مسار O2 في LLVM، وفيه تضمين الدوال (منذ 0.6.0)
-O0 بلا مسار O2: التحسين الخفيف الذي يُشغَّل به البرنامج مباشرة. أسرع بناءً، وأبطأ تنفيذاً
--cpu=native تعليمات معالج هذا الجهاز وميزاته. والملف قد لا يعمل على معالج أقدم: للبناء المحلي
-O مقبول للتوافق ولا أثر له (كان في 0.5.2 يشغّل مسار O1)
--json نتيجة البناء وتشخيصاته بصيغة JSON
--emit-ir=ملف حفظ شيفرة LLVM IR للبرنامج المبني

ومعها خيارات الترجمة المعتادة: --strict، --deny-deprecated، --debug-mem، --wrap-overflow، --no-ffi، --full-buffered، --overlay.

رموز الخروج: 0 بُني الملف، 2 خطأ ترجمة أو ربط (لا ملف)، 1 خطأ استعمال.

الساكن (الافتراضي). الملف فيه البرنامج ومكتبة C (musl) كلها، فلا يعتمد على مكتبة C للنظام ولا على إصدارها. بنص وثيقة المجمّع (docs/build.md)، لا بتجربة هذا الموقع: «جُرّب على دبيان 12 وأوبونتو 22.04 وألباين 3.20 (x86_64)، وفي حاوية ليس فيها ملف واحد غيره. ما يطلبه من الجهاز نواة لينكس x86_64 وحدها؛ لم يُجرَّب على توزيعات أو أنوية أخرى». «مرحبا» 28 ك.ب (في 0.6؛ وبـ 0.10.0 قيس 29640 بايتاً).

الحركي. الملف يعتمد عند التشغيل على مكتبة C للنظام (glibc) وعلى كل مكتبة C يطلبها البرنامج. «مرحبا» 5 ك.ب (في 0.6؛ وبـ 0.10.0 قيس 6488 بايتاً).

برنامج يستعمل مكتبة C خارج libc وlibm (مثل خارجي "z") يُربط حركياً بمكتبات النظام. الملف الناتج يحتاج تلك المكتبة مثبَّتة على الجهاز الذي يعمل عليه، ويحتاج glibc (فلا يعمل على ألباين) بإصدار لا يقل عن إصدار ما استعمله البرنامج من دوالها على جهاز البناء. --static معه خطأ ترجمة.

الربط الحركي لا يحتاج gcc ولا ملفات التطوير: الرابط يربط بالمكتبات المشتركة نفسها. مكتبة في مكان غير معتاد: --link-arg -L<مجلد>.

  1. المجمّع يولّد ملفاً كائنياً فيه البرنامج كله، ومعه دالة main مولَّدة تفعل ما يفعله المجمّع قبل التشغيل المباشر: تصنيف الحروف UTF-8، تفريغ stdout عند كل سطر حين لا يكون طرفية، وتشغيل البرنامج في خيط بمكدس 256 م.ب. وأول ما تفعله دالة البرنامج حارس المكدس: عودية بلا توقف تملأ المكدس فتبلغ الصفحة الحارسة تحته، ومعالج الإشارة (على مكدس بديل) يطبع «تجاوز عمق العودية» ويخرج برمز 3. الحارس نفسه في التشغيل المباشر (منذ 0.6.0؛ كان قبلها عدّاداً للاستدعاءات المتداخلة بحدّ 100000).
  2. الرابط يضيف مكتبة C. لا مكتبة تشغيل للغة ميم: كل دوال التشغيل (النصوص، القوائم، القواميس، عدّ المراجع، كاشف الذاكرة) مولَّدة في الملف الكائني، وهي نفسها في التشغيل المباشر.

فروق عن التشغيل المباشر:

  • MEEM_RC_REPORT يُقرأ عند البناء لا عند تشغيل الملف.
  • Ctrl+C: الإشارة تنهي العملية، والصدفة تبلّغ 130.
  • رموز خارجي تُفحص عند البناء (خطأ ترجمة بموضعه)، ثم يربطها الرابط.

بالترتيب: ما يحدده MEEM_CC (مجمّع C يُستعمل رابطاً)؛ ثم السلسلة المضمَّنة في الحزمة (أو MEEM_TOOLCHAIN)؛ ثم مجمّع C للنظام (cc، gcc، clang)، وهو يربط حركياً إلا مع --static.

المضمَّنة: الرابط mold 2.34.1 ومكتبة musl 1.2.5 الساكنة، كلتاهما برخصة MIT، ومع mold مكتبة libatomic. فالبناء يعمل بلا أي أداة أخرى على الجهاز.

الكاشف في الملف المبني: --debug و--debug-mem

رابط إلى قسم «الكاشف في الملف المبني: --debug و--debug-mem»

الملف المبني بلا كاشف ذاكرة افتراضياً (منذ 0.10.0، والتشغيل المباشر meem ب.م بالكاشف). فالاستعمال بعد التحرير أو التحرير المزدوج عبر اسم آخر فيه سلوك غير معرَّف: ناتج قديم، أو نفايات، أو سقوط. meem build ب.م --debug يبني الكاشف في الملف: الاستعمال بعد التحرير والتحرير المزدوج أخطاء تشغيل بالرسائل نفسها (E0429 وE0430 وE0431…). و--debug-mem مثله ويضيف تقرير ما لم يُحرَّر عند النهاية على stderr. الملف بالكاشف أبطأ وأكبر.

خرج --check --json نفسه (عقد الأدوات) ومعه الحقل build: null إن فشل البناء، وإلا وصف الناتج:

الحقل المعنى
build.output المسار الكامل للملف الناتج
build.object صواب مع --emit-obj
build.static صواب: ملف ساكن بلا اعتماد. خطاء: يعتمد على مكتبة C للنظام وعلى libraries
build.linker مسار الرابط الذي استُعمل
build.optimized صواب إن بُني بمسار O2 (الافتراضي منذ 0.6.0)، وخطاء مع -O0
  • لينكس x86_64 وحده. لا ARM ولا ويندوز ولا ماك.
  • الحركي مربوط بجهاز البناء: يطلب glibc بإصدار ما استعمله من دوالها هناك. الساكن لا قيد عليه.
  • musl غير glibc: دالة C موجودة في glibc وحدها تمرّ من فحص الرموز ثم يرفضها الرابط الساكن برسالة «رمز غير معرَّف»؛ الحل --dynamic. وتوزيع الذاكرة في musl أبطأ من glibc في البرامج الكثيرة الحجز.
  • حزمة المجمّع نفسها تطلب glibc 2.35 أو أحدث. التوزيعات المجرَّبة: أوبونتو 22.04 ودبيان 12. لا تعمل على توزيعات musl (ألباين)؛ الملف الساكن المبني هو الذي يعمل هناك.
  • لا وسائط سطر أوامر للبرنامج: اللغة لا تقرؤها بعد؛ الملف يتجاهل ما يُمرَّر له.
  • رخصة musl (MIT) تطلب إبقاء إشعار حقوقها عند توزيع ملف ساكن؛ نصه في licenses/toolchain-musl-COPYRIGHT داخل الحزمة.