ARMでDを書く方法

こんにちは、Habr!







今日は、Linux上のミニコンピューター(RPI、BBBなど)の開発経験をDプログラミング言語で共有したいと思います。 カットの下で、痛みを伴わずにこれを行う方法に関する完全な指示。 まあ、またはほぼ... =)













なぜd?



仕事で、Dの大ファンであっても、ARMの監視システムを作成することがタスクであったとき、それをメインツールとして使用すべきかどうか疑問に思いました。 一般に、私は気まぐれな人ではなく、私は長い間Dにいるので、試してみる価値があると思った...すべてがそれほど単純ではない。 一方で、特別な問題はありませんでした(コンパイラーの新しいバージョンの到着で残された完全に明確な問題を除く)一方で、ARM向けに開発している人々は、ツールキットがその言葉にまったく対応していないと常に考えることができます。 それはあなた次第です。







ツールキット



同志のD Programming Language



プラグインを使用して、 Visual Studio Code



アドバイスできます。 WebFreak(Jan Jurzitza)。 設定では、常に最新バージョンのserve-d



を使用serve-d



ようにBeta Stream



設定を設定できます。 プラグイン自体が必要なソフトウェアをインストールします。







プロジェクトの一般的な構造



一般的に、(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



アプリケーションが動作するために必要なライブラリ(アームの下でコンパイル)

docker-ctx



-Dockerイメージを組み立てるためのコンテキスト

entry.sh



後でコンテナを起動するたびにいくつかのアクションを実行します。

dub.sdl



-Dのプロジェクトファイル。サードパーティライブラリなどを含めることができます。

build-docker



コンテナビルドスクリプト(基本的に1行ですが、それでも)

ddb



- ddb



D ddb



コンテナ起動スクリプト(1行ですが、実際はより便利です)

ldc



必要なすべてのパラメーターを指定してldcを呼び出すことができるスクリプト

makefile



-armおよび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



    スクリプトがコンパイラとして渡され、環境変数が設定されます
  7. 実行時ライブラリは、 makefile



    内のmakefile



    アップ依存関係として設定され、見つからない場合、 ldc-build-runtime



    プログラムによって収集されldc-build-runtime



  8. 変数はldc



    スクリプトとdub.sdl



    パラメーターにdub.sdl



    ます


メインファイルの内容



Dockerfile



RPI3で記述するため、ベースのdebian:stretch-slim



システムのイメージを選択しますdebian:stretch-slim



gcc-arm-linux-gnueabihf



は公式のraspbianディストリビューションと同じバージョンの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



コンパイラーは、現在のllvm



基づいてコンパイルされるgithub



からldc









entry.sh



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





ここではすべてが簡単です.dpack



フォルダーがない場合は、作成し、 .dpack



を使用して.dpack



へのシンボリックリンクを作成します。

これにより、 dub



によってダウンロードされたパッケージをプロジェクトフォルダーに保存できます。







build-docker、ddb、ldc



これらは3つの単純な単一行ファイルです。 そのうちの2つはオプションですが、便利ですが、Linux(bash)用に作成されています。 Windowsの場合、同様のファイルをローカルスクリプトに作成するか、手動で実行する必要があります。







build-docker



はコンテナアセンブリを開始します(1回だけ呼び出され、Linuxのみ):







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





ddb



はアセンブリ用のコンテナを起動し、パラメータを渡します(Linuxのみ):







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





コンテナ名はdcross



で使用され(名前自体は重要ではありませんが、両方のファイルで一致する必要があります)、 pwd



コマンドを使用して/workdir



現在のディレクトリをDockerfile



ます(ディレクトリはWORKDIR



Dockerfile



として指定されます)(winでは、 %CD%



を使用する必要があるようです) %CD%



)。







ldc



は、環境変数を使用しながら、奇妙なことにldc



起動します(Linuxのみですが、コンテナで起動するため、winでビルドするために変更する必要はありません)。







 #!/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"



アセンブリレシピの一部のフィールドを指定できないためです(たとえば、 lflags "-L.libs" platform="arm"



は、腕の下でビルドする場合にのみリンカーにフラグを追加します)。







メイクファイル



そして、ここが最も興味深いものです。 実際、 make



そのようなビルドには使用されず、このためにdub



を呼び出し、 dub



自体が再構築する必要があるものとしないものを監視します。 しかし、 makefile



の助けを借りて、必要なすべての環境変数が形成され、より複雑なケースで追加のコマンドが実行されます(Cでのライブラリの構築、更新ファイルのパッキングなど)。







makefile



の内容は、他の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



使用すると、ほとんど1つのコマンドでarmとx86の両方でプロジェクトをビルドできます。







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





build-x86



場合、 build-arm



ファイルはbuild-arm



に入ります。







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





誰もが今ウェブを必要としています=)







おわりに



一般に、すべてが一見したほど複雑ではなく、普遍的なアプローチがまだ準備されていないというだけです。 個人的には、 make



なしでやろうとして多くの時間を費やしました。 彼と一緒に、すべてが何らかの形でよりシンプルでより多様になりました。







ただし、DはGoではないことを理解する必要があります。Dでは、外部ライブラリを使用するのが一般的であり、それらのバージョンに注意する必要があります。

arm用のライブラリを取得する最も簡単な方法は、動作中のデバイスからライブラリをコピーすることです。







参照資料



例のソースコードを次に示します。 このリポジトリでは、ロシア語を話すコミュニティが徐々に情報、例、リンクを収集しています。







ここには、YoctoLinux用にビルドする方法などの詳細情報があります。







VKのニュースフィード








All Articles