كيفية كتابة D على ARM

يوم جيد ، هبر!


اليوم أريد أن أشارك تجربتي التطويرية لأجهزة الكمبيوتر المصغرة على لينكس (RPI و BBB وغيرها) بلغة البرمجة D. تحت القطع ، تعليمات كاملة حول كيفية القيام بذلك دون ألم. حسنا ، أو تقريبا ... =)



لماذا د؟


عندما كنت في العمل ، كانت المهمة هي كتابة نظام مراقبة لـ ARM ، حتى كمشجع كبير لـ D ، شككت في ما إذا كان ينبغي اعتباره الأداة الرئيسية. بشكل عام ، أنا لست شخصًا غريب الأطوار ، وقد كنت على D لفترة طويلة ، لذلك اعتقدت أنه يستحق المحاولة و ... ليس كل شيء بهذه البساطة. من ناحية ، لم تكن هناك مشاكل خاصة (باستثناء واحدة غير واضحة تمامًا تركت مع وصول النسخة الجديدة من المترجم) ، من ناحية أخرى ، يمكن للأشخاص الذين يطورون لـ ARM أن يعتقدوا باستمرار أن مجموعة الأدوات ليست جاهزة من الكلمة على الإطلاق. الأمر متروك لك.


مجموعة أدوات


يمكنني تقديم المشورة إلى Visual Studio Code باستخدام المكون الإضافي D Programming Language من الرفيق. WebFreak (جان جورزيتزا). في الإعدادات ، يمكنك ضبط إعداد Beta Stream ليكون دائمًا أحدث إصدار من serve-d . يقوم البرنامج المساعد نفسه بتثبيت البرنامج الضروري.


الهيكل العام للمشروع


بشكل عام ، تبين أنه مرتبك تمامًا (مقارنة بالمشروع المعتاد على D) ، ولكن ، كما يبدو لي ، فهو مرن ومريح للغاية.


 . ├── arm-lib/ |  ├── libcrypto.a |  ├── libssl.a |  └── libz.a ├── docker-ctx/ |  ├── Dockerfile |  └── entry.sh ├── source |  └── app.d ├── .gitignore ├── build-docker ├── ddb ├── dub.sdl ├── ldc └── makefile 

arm-lib - المكتبات اللازمة arm-lib للعمل (تم تجميعه تحت الذراع)
docker-ctx - سياق لتجميع صورة عامل الميناء
entry.sh - سيتم تنفيذ بعض الإجراءات حول كل عملية إطلاق لاحقة للحاوية ، والتي سيتم إجراء ذلك لاحقًا
dub.sdl - ملف مشروع في D ، يسمح لك بتضمين مكتبات الطرف الثالث وأكثر من ذلك بكثير
build-docker - البرنامج النصي لبناء الحاوية (بشكل أساسي سطر واحد ، ولكن لا يزال)
ddb - ddb D builder - نص برمجي لإطلاق الحاوية (أيضًا سطر واحد ، ولكن في الواقع أكثر ملاءمة)
ldc - نص برمجي يسمح لك باستدعاء ldc بجميع المعلمات الضرورية
makefile - يحتوي على وصفات بناء للذراع و x86 وإجراءات إضافية
source/app.d - مصادر المشروع


بضع كلمات عن arm-lib .
هناك الملفات اللازمة لكي يعمل vibe. إن إضافة الملفات الثنائية إلى المستودع هي صيغة سيئة. ولكن هنا لتبسيط حياتك ، من الأسهل القيام بذلك. يمكنك إضافتها داخل الحاوية ، ولكن بعد ذلك ، من أجل تشكيل وصفة تجميع الحاوية بالكامل ، ستحتاج إلى تخزين مجلد arm-lib في dockert-ctx . الطعم واللون ...


خوارزمية التجميع العام


 ./ddb make 

  1. يبدأ ddb الحاوية ، وينفذ البرنامج النصي entry.sh
  2. entry.sh بتكوين dub قليلاً بحيث يستخدم مجلد المكتبة داخل الحاوية ، والذي سيكون موجودًا في الدليل الحالي ، مما سيسمح لك بعدم ضخ وتجميع المكتبات المستخدمة في المشروع عند إعادة تشغيل التجميع
  3. entry.sh ينتهي بتمرير التحكم إلى أمر الإدخال ( make في حالتنا)
  4. make بدوره يقرأ makefile
  5. يتم تخزين جميع العلامات الخاصة بالتجميع المتقاطع ودليل البناء في ملف makefile ، ويتم تشكيل خط نداء dub
  6. عند استدعاء dub ldc البرنامج النصي ldc من الدليل الحالي عند تعيين المترجم والبيئة
  7. يتم تعيين مكتبات وقت التشغيل على أنها تبعيات makefile في ملف makefile ، والتي ، إذا كانت مفقودة ، يتم جمعها بواسطة برنامج ldc-build-runtime
  8. يتم تمرير المتغيرات إلى البرنامج النصي ldc وإلى معلمات dub.sdl

محتويات الملفات الرئيسية


ملف Dockerfile


نظرًا لأننا سنكتب تحت RPI3 ، فإننا نختار صورة نظام gcc-arm-linux-gnueabihf debian:stretch-slim ، حيث يستخدم gcc-arm-linux-gnueabihf نفس الإصدار من glibc مثل التوزيع الرسمي لراسبيني (كانت هناك مشكلة في فيدورا حيث استخدم مشرف المترجم المتقاطع إصدارًا جديدًا جدًا من glibc )


 FROM debian:stretch-slim RUN apt-get update && apt-get install -y \ make cmake bash p7zip-full tar wget gpg xz-utils \ gcc-arm-linux-gnueabihf ca-certificates \ && apt-get autoremove -y && apt-get clean ARG ldcver=1.11.0 RUN wget -O /root/ldc.tar.xz https://github.com/ldc-developers/ldc/releases/download/v$ldcver/ldc2-$ldcver-linux-x86_64.tar.xz \ && tar xf /root/ldc.tar.xz -C /root/ && rm /root/ldc.tar.xz ENV PATH "/root/ldc2-$ldcver-linux-x86_64/bin:$PATH" ADD entry.sh /entry.sh RUN chmod +x /entry.sh WORKDIR /workdir ENTRYPOINT [ "/entry.sh" ] 

يتم ldc مترجم ldc من github ، حيث يتم تجميعه استنادًا إلى llvm الحالي.


entry.sh


 #!/bin/bash if [ ! -d ".dpack" ]; then mkdir .dpack fi ln -s $(pwd)/.dpack /root/.dub exec $@ 

كل شيء بسيط هنا: إذا لم يكن هناك مجلد .dpack ، .dpack بإنشاء واستخدام .dpack لإنشاء ارتباط رمزي إلى /root/.dub .
سيسمح لك هذا بتخزين الحزم التي تم تنزيلها بواسطة dub في مجلد المشروع.


بناء عامل الميناء ، ddb ، ldc


هذه هي ثلاثة ملفات سطر واحد بسيطة. اثنان منهم اختياريان ، لكنهما مناسبان ، ولكنهما مكتوبان لـ linux (bash). بالنسبة إلى النوافذ ، سيكون عليك إنشاء ملفات مماثلة على البرنامج النصي المحلي أو تشغيلها يدويًا.


build-docker ببدء بناء الحاوية (يُسمى مرة واحدة فقط لـ Linux):


 #!/bin/bash docker build -t dcross docker-ctx 

ddb بتشغيل الحاوية للتجميع ويمرر المعلمات (لينكس فقط):


 #!/bin/bash docker run -v `pwd`:/workdir -t --rm dcross $@ 

يرجى ملاحظة أن اسم الحاوية يستخدم dcross (لا يهم الاسم نفسه ، ولكن يجب أن يتطابق في كلا الملفين) ويتم استخدام الأمر pwd لإعادة Dockerfile الدليل الحالي في /workdir (يتم تحديد الدليل باعتباره WORKDIR في ملف Dockerfile ) (في الفوز ، يبدو أنك بحاجة إلى استخدام %CD% ).


يبدأ ldc ، بشكل غريب بما فيه الكفاية ، أثناء استخدام متغيرات البيئة (فقط لينكس ، لكنه يبدأ في الحاوية ، لذلك لا يلزم تغييره للبناء تحت الفوز):


 #!/bin/bash $LDC $LDC_FLAGS $@ 

dub.sdl


على سبيل المثال ، سيكون الأمر بسيطًا جدًا:


 name "chw" description "Cross Hello World" license "MIT" targetType "executable" targetPath "$TP" dependency "vibe-d" version="~>0.8.4" dependency "vibe-d:tls" version="~>0.8.4" subConfiguration "vibe-d:tls" "openssl-1.1" 

يتم أخذ targetPath من متغير البيئة لأن dub لا يمكنه تحديد بعض حقول وصفة التجميع حسب النظام الأساسي (على سبيل المثال ، lflags "-L.libs" platform="arm" ستضيف علامة إلى الرابط فقط عند البناء تحت الذراع).


makefile


وهنا الأكثر إثارة للاهتمام. في الواقع ، لا يستخدم make للبناء على هذا النحو ، فهو dub على هذا الأمر ، dub نفسه نفسه ما يجب إعادة تجميعه وما لا يجب إعادة تجميعه. ولكن بمساعدة ملف makefile تكوين جميع متغيرات البيئة الضرورية ، يتم تنفيذ أوامر إضافية في حالات أكثر تعقيدًا (بناء مكتبات في C ، وملفات تحديث الحزم ، وما إلى ذلك).


محتويات ملف makefile أكبر من البقية:


 #     arm arch = arm # target path -- ,      TP = build-$(arch) LDC_DFLAGS = -mtriple=armv7l-linux-gnueabihf -disable-inlining -mcpu=cortex-a8 #         EMPTY := SPACE :=$(EMPTY) $(EMPTY) LDC_BRT_DFLAGS = $(subst $(SPACE),;,$(LDC_DFLAGS)) ifeq ($(force), y) #        #  , .. dub      FORCE = --force else FORCE = endif ifeq ($(release), y) BUILD_TYPE = --build=release else BUILD_TYPE = endif DUB_FLAGS = build --parallel --compiler=./ldc $(FORCE) $(BUILD_TYPE) $(info DUB_FLAGS: $(DUB_FLAGS)) #     LDC = ldc2 LDC_BRT = ldc-build-runtime #    ldc,    runtime   ARM LDC_RT_DIR = .ldc-rt #  gcc      GCC = arm-linux-gnueabihf-gcc ifeq ($(arch), x86) LDC_FLAGS = else ifeq ($(arch), arm) LDC_FLAGS = $(LDC_DFLAGS) -LL./$(LDC_RT_DIR)/lib -LL./arm-lib -gcc=$(GCC) else $(error unknown arch) endif DUB = TP=$(TP) LDC=$(LDC) LDC_FLAGS="$(LDC_FLAGS)" dub $(DUB_FLAGS) #      .PHONY: all clean rtlibs stat #    all: rtlibs $(DUB) DRT_LIBS=$(addprefix $(LDC_RT_DIR)/lib/, libdruntime-ldc.a libdruntime-ldc-debug.a libphobos2-ldc.a libphobos2-ldc-debug.a) $(DRT_LIBS): CC=$(GCC) $(LDC_BRT) -j8 --dFlags="$(LDC_BRT_DFLAGS)" --buildDir=$(LDC_RT_DIR) \ --targetSystem="Linux;UNIX" BUILD_SHARED_LIBS=OFF # D runtime  ARM rtlibs: $(DRT_LIBS) #      stat: find source -name '*.d' | xargs wc -l clean: rm -rf $(TP) rm -rf .dub $(LDC_BRT) --buildDir=$(LDC_RT_DIR) --resetOnly 

يتيح لك ملف makefile بناء مشروع تحت ذراع و x86 بأمر واحد تقريبًا:


 ./ddb make ./ddb make arch=x86 #     x86 make arch=x86 #   host    ldc 

تدخل ملفات arm في build-arm ، بالنسبة إلى x86 في build-x86 .


التطبيق د


حسنًا ، بالنسبة app.d ، للصورة الكاملة ، كود app.d :


 import vibe.core.core : runApplication; import vibe.http.server; void handleRequest(scope HTTPServerRequest req, scope HTTPServerResponse res) { if (req.path == "/") res.writeBody("Hello, World!", "text/plain"); } void main() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "0.0.0.0"]; auto l = listenHTTP(settings, &handleRequest); scope (exit) l.stopListening(); runApplication(); } 

الجميع الآن بحاجة إلى الويب =)


الخلاصة


بشكل عام ، كل شيء ليس معقدًا للغاية كما يبدو للوهلة الأولى ، إنه فقط أن النهج العالمي ليس جاهزًا بعد. أنا شخصياً قضيت الكثير من الوقت أحاول الاستغناء عنه. معه ، أصبح كل شيء أكثر بساطة وأكثر تنوعًا.


ولكن عليك أن تفهم أن D ليس Go ، في D من المعتاد استخدام المكتبات الخارجية ويجب أن تكون حذرًا في إصداراتها.
أسهل طريقة للحصول على مكتبة للذراع هي نسخها من جهاز يعمل.


المراجع


هنا هو رمز المصدر للمثال. في هذا المستودع ، يقوم المجتمع الناطق باللغة الروسية بجمع المعلومات والأمثلة والروابط تدريجيًا.


هناك معلومات إضافية هنا ، مثل كيفية إنشاء YoctoLinux.


موجز الأخبار في VK

Source: https://habr.com/ru/post/ar428982/


All Articles