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
ddb
démarre le conteneur, exécute le script entry.sh
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'assemblyentry.sh
finit par passer le contrÎle à la commande d'entrée ( make
dans notre cas)make
Ă son tour lit makefile
- 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 - 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 - 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
- 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