Comment écrire D sur ARM

Bonjour, Habr!


Aujourd'hui, je souhaite partager mon expérience de développement de mini-ordinateurs sous linux (RPI, BBB et autres) en langage de programmation D. Sous la coupe, des instructions complÚtes sur la façon de le faire sans douleur. Eh bien, ou presque ... =)



Pourquoi d?


Au travail, la tĂąche consistait Ă  Ă©crire un systĂšme de surveillance pour ARM, mĂȘme en tant que grand fan de D, je me demandais s'il devait ĂȘtre considĂ©rĂ© comme l'outil principal. En gĂ©nĂ©ral, je ne suis pas une personne fantasque, et je suis sur D depuis longtemps, donc j'ai pensĂ© que ça valait la peine d'essayer et ... tout n'est pas si simple. D'une part, il n'y a pas eu de problĂšmes particuliers (Ă  l'exception d'un problĂšme pas tout Ă  fait clair qui est parti avec l'arrivĂ©e de la nouvelle version du compilateur), d'autre part, les personnes qui dĂ©veloppent pour ARM peuvent constamment penser que la boĂźte Ă  outils n'est pas prĂȘte du tout. Cela dĂ©pend de vous.


BoĂźte Ă  outils


Je peux conseiller Visual Studio Code avec le plugin D Programming Language de camarade. WebFreak (Jan Jurzitza). Dans les paramĂštres, vous pouvez dĂ©finir le paramĂštre Beta Stream pour toujours disposer de la derniĂšre version de serve-d . Le plugin lui-mĂȘme installe le logiciel nĂ©cessaire.


Structure générale du projet


En général, cela s'est avéré assez confus (en comparaison avec le projet habituel sur D), mais, il me semble, il est assez flexible et pratique.


 . ├── 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 - bibliothÚques nécessaires au fonctionnement de notre application (compilées sous arm)
docker-ctx - contexte pour assembler une image docker
entry.sh - effectuera certaines actions à chaque lancement ultérieur du conteneur, dont plus tard
dub.sdl - fichier de projet en D, vous permet d'inclure des bibliothĂšques tierces et bien plus encore
build-docker - script de construction de conteneur (essentiellement 1 ligne, mais toujours)
ddb - docker D builder - script de lancement de conteneur (également une ligne, mais en fait plus pratique)
ldc - un script qui vous permet d'appeler ldc avec tous les paramÚtres nécessaires
makefile - contient des recettes de construction pour arm et x86 et des actions supplémentaires
source/app.d - sources du projet


Quelques mots sur arm-lib .
Il y a les fichiers nécessaires pour que vibe fonctionne. L'ajout de fichiers binaires au référentiel est une mauvaise forme. Mais ici, pour vous simplifier la vie, il est plus facile de faire exactement cela. Vous pouvez les ajouter à l'intérieur du conteneur, mais ensuite, afin de former entiÚrement la recette d'assemblage du conteneur, vous devrez stocker le dossier arm-lib dans dockert-ctx . Le goût et la couleur ...


Algorithme d'assemblage général


 ./ddb make 

  1. ddb démarre le conteneur, exécute le script entry.sh
  2. entry.sh configure dub peu le dub pour qu'il utilise le dossier de bibliothÚque à l'intérieur du conteneur, qui sera situé dans le répertoire courant, ce qui vous permettra de ne pas pomper et collecter les bibliothÚques utilisées dans le projet lorsque vous redémarrez l'assembly
  3. entry.sh finit par passer le contrÎle à la commande d'entrée ( make dans notre cas)
  4. make Ă  son tour lit makefile
  5. tous les drapeaux pour la compilation croisée et le répertoire de construction sont stockés dans le makefile , une ligne d'appel dub est formée
  6. lors de l'appel à dub script ldc du répertoire courant est passé en tant que compilateur et les variables d'environnement sont définies
  7. les bibliothÚques d'exécution sont définies comme des dépendances de maquillage dans le makefile , qui, si elles sont manquantes, sont collectées par le programme ldc-build-runtime
  8. les variables sont passées au script ldc et aux paramÚtres dub.sdl

Le contenu des fichiers principaux


Dockerfile


Comme nous Ă©crirons sous RPI3, nous sĂ©lectionnons l'image du systĂšme debian:stretch-slim base debian:stretch-slim , oĂč gcc-arm-linux-gnueabihf utilise la mĂȘme version de glibc que la distribution officielle de raspbian (il y avait un problĂšme avec fedora, oĂč le mainteneur du compilateur croisĂ© utilisait une version trop rĂ©cente de 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" ] 

Le compilateur ldc partir de github , oĂč il est compilĂ© sur la base du llvm actuel.


entry.sh


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

Tout est simple ici: s'il n'y a pas de dossier .dpack , alors créez, utilisez .dpack pour créer un lien symbolique vers /root/.dub .
Cela vous permettra de stocker les packages téléchargés par le dub dans le dossier du projet.


build-docker, ddb, ldc


Ce sont trois fichiers simples sur une seule ligne. Deux d'entre eux sont facultatifs, mais pratiques, mais écrits pour linux (bash). Pour Windows, vous devrez créer des fichiers similaires sur le script local ou simplement l'exécuter à la main.


build-docker démarre la construction du conteneur (appelé une fois, uniquement pour linux):


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

ddb lance le conteneur pour l'assemblage et passe les paramĂštres (linux uniquement):


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

Veuillez noter que le nom du conteneur est utilisĂ© dcross (le nom lui-mĂȘme n'a pas d'importance, mais il doit correspondre dans les deux fichiers) et la commande pwd est utilisĂ©e pour Dockerfile rĂ©pertoire actuel dans /workdir (le rĂ©pertoire est spĂ©cifiĂ© comme WORKDIR dans le Dockerfile ) (dans win, il semble, vous devez utiliser %CD% ).


ldc dĂ©marre ldc , curieusement, en utilisant des variables d’environnement (uniquement linux, mais il dĂ©marre dans le conteneur, il n’a donc pas besoin d’ĂȘtre modifiĂ© pour ĂȘtre construit sous win):


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

dub.sdl


Par exemple, ce sera assez simple:


 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 est extrait de la variable d'environnement car dub ne peut pas spécifier les champs de la recette d'assemblage par plate-forme (par exemple, lflags "-L.libs" platform="arm" ajoutera un indicateur à l'éditeur de liens uniquement lors de la construction sous arm).


makefile


Et voici le plus intĂ©ressant. En fait, make pas utilisĂ© pour construire en tant que tel, il appelle un dub pour cela, et dub lui-mĂȘme surveille ce qui doit ĂȘtre rĂ©assemblĂ© et ce qui ne l'est pas. Mais Ă  l'aide d'un makefile toutes les variables d'environnement nĂ©cessaires sont formĂ©es, des commandes supplĂ©mentaires sont exĂ©cutĂ©es dans des cas plus complexes (construction de bibliothĂšques en C, compression des fichiers de mise Ă  jour, etc.).


Le contenu du makefile plus grand que le reste:


 #     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 

Un tel makefile vous permet de construire un projet sous arm et x86 avec presque une commande:


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

Les fichiers pour arm entrent dans build-arm , pour x86 dans build-x86 .


app.d


Eh bien, pour l'apéritif, pour l'image complÚte, le code 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(); } 

Tout le monde a maintenant besoin du web =)


Conclusion


En gĂ©nĂ©ral, tout n'est pas aussi compliquĂ© qu'il n'y paraĂźt Ă  premiĂšre vue, c'est juste qu'une approche universelle n'est pas encore prĂȘte. Personnellement, j'ai passĂ© beaucoup de temps Ă  essayer de me passer de make . Avec lui, tout est devenu plus simple et plus variĂ©.


Mais vous devez comprendre que D n'est pas Go, dans D, il est habituel d'utiliser des bibliothĂšques externes et vous devez ĂȘtre prudent avec leurs versions.
La façon la plus simple d'obtenir une bibliothÚque pour armer est de la copier à partir d'un périphérique de travail.


Les références


Voici le code source de l'exemple. Dans ce référentiel, la communauté russophone recueille progressivement des informations, des exemples, des liens.


Il y a des informations supplémentaires ici, comme comment construire pour YoctoLinux.


Fil de nouvelles en VK

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


All Articles