يوم جيد ، هبر!
اليوم أريد أن أشارك تجربتي التطويرية لأجهزة الكمبيوتر المصغرة على لينكس (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
- يبدأ
ddb
الحاوية ، وينفذ البرنامج النصي entry.sh
entry.sh
بتكوين dub
قليلاً بحيث يستخدم مجلد المكتبة داخل الحاوية ، والذي سيكون موجودًا في الدليل الحالي ، مما سيسمح لك بعدم ضخ وتجميع المكتبات المستخدمة في المشروع عند إعادة تشغيل التجميعentry.sh
ينتهي بتمرير التحكم إلى أمر الإدخال ( make
في حالتنا)make
بدوره يقرأ makefile
- يتم تخزين جميع العلامات الخاصة بالتجميع المتقاطع ودليل البناء في ملف
makefile
، ويتم تشكيل خط نداء dub
- عند استدعاء
dub
ldc
البرنامج النصي ldc
من الدليل الحالي عند تعيين المترجم والبيئة - يتم تعيين مكتبات وقت التشغيل على أنها تبعيات
makefile
في ملف makefile
، والتي ، إذا كانت مفقودة ، يتم جمعها بواسطة برنامج ldc-build-runtime
- يتم تمرير المتغيرات إلى البرنامج النصي
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