Wie schreibe ich D auf ARM

Guten Tag, Habr!


Heute möchte ich meine Entwicklungserfahrung fĂŒr Mini-Computer unter Linux (RPI, BBB und andere) in der Programmiersprache D teilen. Unter dem Schnitt finden Sie vollstĂ€ndige Anweisungen, wie Sie dies ohne Schmerzen tun können. Na ja, oder fast ... =)



Warum d?


Bei der Arbeit bestand die Aufgabe darin, ein Überwachungssystem fĂŒr ARM zu schreiben, selbst als großer Fan von D, und ich bezweifelte, dass es als Hauptwerkzeug verwendet werden sollte. Im Allgemeinen bin ich keine skurrile Person, und ich bin schon lange auf D, also dachte ich, es wĂ€re einen Versuch wert und ... nicht alles ist so einfach. Einerseits gab es keine besonderen Probleme (mit Ausnahme eines nicht ganz klaren, das mit der EinfĂŒhrung der neuen Version des Compilers einherging), andererseits können Leute, die fĂŒr ARM entwickeln, stĂ€ndig denken, dass das Toolkit ĂŒberhaupt nicht bereit ist. Es liegt an Ihnen.


Toolkit


Ich kann Visual Studio Code mit dem D Programming Language Plugin von comrade empfehlen. WebFreak (Jan Jurzitza). In den Einstellungen können Sie die Beta Stream Einstellung so einstellen, dass immer die neueste Version von serve-d verfĂŒgbar ist. Das Plugin selbst installiert die erforderliche Software.


Allgemeine Struktur des Projekts


Im Allgemeinen stellte sich heraus, dass es ziemlich verwirrt war (im Vergleich zu dem ĂŒblichen Projekt auf D), aber wie es mir scheint, ist es ziemlich flexibel und bequem.


 . ├── 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 - Bibliotheken, die fĂŒr die Funktion unserer Anwendung erforderlich sind (kompiliert unter arm)
docker-ctx - Kontext zum Zusammenstellen eines Docker-Images
entry.sh - fĂŒhrt einige Aktionen fĂŒr jeden spĂ€teren Start des Containers aus, ĂŒber die spĂ€ter
dub.sdl - Projektdatei in D, mit der Sie Bibliotheken von Drittanbietern und vieles mehr dub.sdl können
build-docker - Container-Build-Skript (im Wesentlichen 1 Zeile, aber immer noch)
ddb - ddb D builder - Container- ddb (auch eine Zeile, aber eigentlich bequemer)
ldc - ein Skript, mit dem Sie ldc mit allen erforderlichen Parametern aufrufen können
makefile - enthĂ€lt Build-Rezepte fĂŒr Arm und x86 sowie zusĂ€tzliche Aktionen
source/app.d - source/app.d


Ein paar Worte zu arm-lib .
Es gibt die Dateien, die erforderlich sind, damit Vibe funktioniert. Das HinzufĂŒgen von BinĂ€rdateien zum Repository ist eine schlechte Form. Um Ihr Leben zu vereinfachen, ist es hier jedoch einfacher, genau das zu tun. Sie können sie in den Container dockert-ctx . Um das Rezept fĂŒr die Containerassemblierung vollstĂ€ndig zu dockert-ctx , mĂŒssen Sie den Ordner arm-lib in dockert-ctx speichern. Der Geschmack und die Farbe ...


Allgemeiner Montagealgorithmus


 ./ddb make 

  1. ddb startet den Container und fĂŒhrt das Skript entry.sh
  2. entry.sh konfiguriert dub wenig so, dass es den Bibliotheksordner im Container verwendet, der sich im aktuellen Verzeichnis befindet, sodass Sie die im Projekt verwendeten Bibliotheken beim Neustart der Assembly nicht herauspumpen und sammeln können
  3. entry.sh am Ende die Kontrolle an den Eingabebefehl (in unserem Fall make )
  4. make liest wiederum makefile
  5. Alle Flags fĂŒr Cross-Compilation und Build-Verzeichnis werden im makefile gespeichert, eine dub Call-Line wird gebildet
  6. Beim Aufruf von dub ldc Skript aus dem aktuellen Verzeichnis als Compiler ĂŒbergeben und Umgebungsvariablen festgelegt
  7. Laufzeitbibliotheken werden im makefile als Make-up-AbhÀngigkeiten festgelegt, die, falls sie fehlen, vom Programm ldc-build-runtime erfasst werden
  8. Variablen werden an das ldc Skript und an die dub.sdl Parameter ĂŒbergeben

Der Inhalt der Hauptdateien


Dockerfile


Da wir unter RPI3 schreiben werden, wÀhlen wir das Image des Basis- debian:stretch-slim Systems aus debian:stretch-slim , wobei gcc-arm-linux-gnueabihf dieselbe Version von glibc wie die offizielle Raspbian-Distribution verwendet (es gab ein Problem mit fedora, bei dem der Cross-Compiler-Betreuer eine zu frische Version von 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" ] 

Der ldc Compiler wird von github ldc und dort basierend auf dem aktuellen llvm .


entry.sh


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

Hier ist alles einfach: Wenn es keinen .dpack Ordner gibt, erstellen Sie mit .dpack einen symbolischen Link zu /root/.dub .
Auf diese Weise können Sie die vom dub heruntergeladenen Pakete im Projektordner speichern.


Build-Docker, ddb, ldc


Dies sind drei einfache einzeilige Dateien. Zwei davon sind optional, aber praktisch, aber fĂŒr Linux (Bash) geschrieben. FĂŒr Windows mĂŒssen Sie Ă€hnliche Dateien im lokalen Skript erstellen oder einfach von Hand ausfĂŒhren.


build-docker startet den Container-Build (einmal aufgerufen, nur fĂŒr Linux):


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

ddb startet den Container fĂŒr die Assembly und ĂŒbergibt Parameter (nur Linux):


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

Bitte beachten Sie, dass der Containername dcross verwendet dcross (der Name selbst spielt keine Rolle, muss aber in beiden Dateien ĂŒbereinstimmen) und der Befehl pwd verwendet wird, Dockerfile aktuelle Verzeichnis in /workdir (das Verzeichnis wird in der Dockerfile WORKDIR als WORKDIR Dockerfile ) (in win mĂŒssen Sie anscheinend %CD% ).


ldc startet ldc seltsamerweise unter Verwendung von Umgebungsvariablen (nur Linux, aber es startet im Container, sodass es nicht geÀndert werden muss, um unter Win zu erstellen):


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

dub.sdl


Zum Beispiel wird es ganz einfach sein:


 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 wird aus der Umgebungsvariablen ĂŒbernommen, da dub keine Felder des Assembly-Rezepts nach Plattform angeben kann (z. B. lflags "-L.libs" platform="arm" fĂŒgt dem Linker nur dann ein Flag hinzu, wenn unter arm erstellt wird).


Makefile


Und hier ist das interessanteste. TatsĂ€chlich wird make nicht zum Erstellen als solches verwendet, es wird ein dub dafĂŒr aufgerufen, und der dub selbst ĂŒberwacht, was wieder zusammengesetzt werden muss und was nicht. Mit Hilfe von makefile alle erforderlichen Umgebungsvariablen gebildet und in komplexeren FĂ€llen zusĂ€tzliche Befehle ausgefĂŒhrt (Erstellen von Bibliotheken in C, Packen von Aktualisierungsdateien usw.).


Der Inhalt des makefile grĂ¶ĂŸer als der Rest:


 #     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 

Mit einem solchen makefile können Sie ein Projekt unter Arm und x86 mit fast einem Befehl erstellen:


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

Dateien fĂŒr arm werden in build-arm , fĂŒr x86 in build-x86 .


app.d


Nun, fĂŒr die Vorspeise, fĂŒr das ganze Bild, app.d der app.d Code:


 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(); } 

Jeder braucht jetzt web =)


Fazit


Im Allgemeinen ist nicht alles so kompliziert, wie es auf den ersten Blick scheint. Es ist nur so, dass ein universeller Ansatz noch nicht fertig ist. Persönlich habe ich viel Zeit damit verbracht, auf make . Bei ihm ging alles irgendwie einfacher und abwechslungsreicher.


Sie mĂŒssen jedoch verstehen, dass D nicht Go ist. In D ist es ĂŒblich, externe Bibliotheken zu verwenden, und Sie mĂŒssen mit deren Versionen vorsichtig sein.
Der einfachste Weg, eine Bibliothek fĂŒr Arm zu erhalten, besteht darin, sie von einem ArbeitsgerĂ€t zu kopieren.


Referenzen


Hier ist der Quellcode fĂŒr das Beispiel. In diesem Repository sammelt die russischsprachige Gemeinschaft nach und nach Informationen, Beispiele und Links.


Hier finden Sie zusĂ€tzliche Informationen, z. B. zum Erstellen fĂŒr YoctoLinux.


Newsfeed in VK

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


All Articles